One of the things I enjoyed working with graphics was manually constructing the textures such as the sand normal map which gives it a lot of dimension where the grass was a lot less successful working with just noise to simulate grass blades. The water I found worked the best. The asset I used rendered a photoreal animated texture of waves with a reflective map however a big issue was that it wasnt transparent and I couldn't make it produce transparency without interfering the graphic script so I rebuild my water from scratch. First I figured out what settings to build the wave refraction on the surface of my water object while adding translucency, then I simply duplicated the texture and had them move horizontally in a sin motions to simulate the movement of water.
Tuesday, December 11, 2018
Unity Virtual Project: Final
For my finished VR project I worked with the terrain tool as well as looked at some other graphical features of Unity. In hindsight I think I should've attempted a more directed look rather than just a conventional semi photoreal look to the project. The Particle also no longer roots out which I just removed as trying to make it more responsive to searching out nodes was looking at a bigger and more complex system as well I had to account for memory limits and at the time I didn't have a good understanding on the limits of the VR rig. I was able to make the Nodes span out over an area and then raycast to find the terrain below it and match the height of each point so they nicely blanket the surface. Sadly a lot of the functions of the particle ended up getting cut as I mentioned earlier this was due to the amount of overhead just to make a single particle function properly in a network and migrating the code over to the line renderer which due to my oversight created a lot of overhead for restructuring a lot of the behaviour.
One of the things I enjoyed working with graphics was manually constructing the textures such as the sand normal map which gives it a lot of dimension where the grass was a lot less successful working with just noise to simulate grass blades. The water I found worked the best. The asset I used rendered a photoreal animated texture of waves with a reflective map however a big issue was that it wasnt transparent and I couldn't make it produce transparency without interfering the graphic script so I rebuild my water from scratch. First I figured out what settings to build the wave refraction on the surface of my water object while adding translucency, then I simply duplicated the texture and had them move horizontally in a sin motions to simulate the movement of water.
One of the things I enjoyed working with graphics was manually constructing the textures such as the sand normal map which gives it a lot of dimension where the grass was a lot less successful working with just noise to simulate grass blades. The water I found worked the best. The asset I used rendered a photoreal animated texture of waves with a reflective map however a big issue was that it wasnt transparent and I couldn't make it produce transparency without interfering the graphic script so I rebuild my water from scratch. First I figured out what settings to build the wave refraction on the surface of my water object while adding translucency, then I simply duplicated the texture and had them move horizontally in a sin motions to simulate the movement of water.
Unity Virtual Project: Progress 2
After reviewing Scriptable Objects I learned that they are actually way more useful than I thought just not useful for my actual project. Scriptable objects cant be edited on the GameObject but one can make new instances and save them as their own separate data class which is useful for large systems that need long term memory or making an array of different settings for a set of objects.
The VR system is still unstable but I was able to make the particles pass information between eachother and created an off state so that they enter a rest state after a few moments so that takes a lot of stress of of the CPU having to update so much of the worldspace. I've also set them to update slower the larger they get so as the network expands it also slows down the component referencing which is taxing in large amounts or at least the way I organized it.
Unity Virtual Project: Progress 2.5
Working on my Game project in my free time I was able to make a for loop system that reads all the attack points in my scriptable objects and then move onto the next attack if the player presses the attack button again.
I did a bunch of coding in class time and I was able to make the amount of resources stored in each object slow its update speed so as parts grow larger they will update slower and that helps stop them from expanding too much and causing visual errors. I also set the particles to make branches out of Lines instead of making new objects for every space, this way I reduce each connection to 1 object despite the distance and I can render them using the Line Renderer component which is a bit tricky to use but is 2d while matching the camera so it saves processing time. now I just need to work on a scene to use it in to complete the experience.
I did a bunch of coding in class time and I was able to make the amount of resources stored in each object slow its update speed so as parts grow larger they will update slower and that helps stop them from expanding too much and causing visual errors. I also set the particles to make branches out of Lines instead of making new objects for every space, this way I reduce each connection to 1 object despite the distance and I can render them using the Line Renderer component which is a bit tricky to use but is 2d while matching the camera so it saves processing time. now I just need to work on a scene to use it in to complete the experience.
Saturday, November 24, 2018
Unity Virtual Project : Progress 1.5
November 21, 2018
In class Thursday I was able to create a functioning particle that would duplicate itself in order to connect to resource nodes I had 2 major problems: 1 updating so many gameobjects was causing a massive bottleneck, 2 gameobjects would duplicate into eachother. I'm working on a fix to reduce massive clusters of objects by representing them as a cluster via a larger object in their place while deleting the group of objects as well I've removed their rigidbody so that the amount of physics calculations is minimal, they are currently only a mesh and a collider. 1 problem was using the collision functions as they are reliant on gameobjects so instead I've used a new function I came across: "OverlapSphere" which outputs a list of colliders in a radius. I am unsure of how this function works, I can only assume it functions similarly to a raycast in how it's calculating 3D space without using physics. I've used this function to gather the duplicating objects around each and delete any that begin overlapping, problem is that more struggle to fill in it's place leading to the same result however after time it seems to find a medium where it has connected to the node and doesnt overlap. The main issue now its that when I try to scale up the duplicates the collisions cause it to be deleted by the other duplicates now overlapping, I'm going to attempt to build a heirarchy, as simple int that prioritizes larger duplicates over smaller to prevent deletion.
When I was researching new tools I came across 2 interesting objects, The first was Unity's scriptableObject Im unsure how to properly use them but they seem limited in how they effect the Scene unlike MonoBehaviour which can interact with Unity's refresh and physics routines. Another useful object was the C# base class type, unlike scriptableObjects these could be written to in the Unity editor inspector by using the Serializable attribute which access of classes in Unity whereas scriptableObjects simply gives us a namespace for object that would be the same for each. The significance of this is that I can now attach this to a multitude of objects but manually customize different prefabs with the same script. This I unfortunately tested in my IRIS game project as I was working on this on a break and as the Virtual project is more procedural based but I feel like this is definitely a useful tool. I will need to test accessing and adding it to Gameobjects in game time to see if it's stable for that purpose before I start using it standard.
In class Thursday I was able to create a functioning particle that would duplicate itself in order to connect to resource nodes I had 2 major problems: 1 updating so many gameobjects was causing a massive bottleneck, 2 gameobjects would duplicate into eachother. I'm working on a fix to reduce massive clusters of objects by representing them as a cluster via a larger object in their place while deleting the group of objects as well I've removed their rigidbody so that the amount of physics calculations is minimal, they are currently only a mesh and a collider. 1 problem was using the collision functions as they are reliant on gameobjects so instead I've used a new function I came across: "OverlapSphere" which outputs a list of colliders in a radius. I am unsure of how this function works, I can only assume it functions similarly to a raycast in how it's calculating 3D space without using physics. I've used this function to gather the duplicating objects around each and delete any that begin overlapping, problem is that more struggle to fill in it's place leading to the same result however after time it seems to find a medium where it has connected to the node and doesnt overlap. The main issue now its that when I try to scale up the duplicates the collisions cause it to be deleted by the other duplicates now overlapping, I'm going to attempt to build a heirarchy, as simple int that prioritizes larger duplicates over smaller to prevent deletion.
When I was researching new tools I came across 2 interesting objects, The first was Unity's scriptableObject Im unsure how to properly use them but they seem limited in how they effect the Scene unlike MonoBehaviour which can interact with Unity's refresh and physics routines. Another useful object was the C# base class type, unlike scriptableObjects these could be written to in the Unity editor inspector by using the Serializable attribute which access of classes in Unity whereas scriptableObjects simply gives us a namespace for object that would be the same for each. The significance of this is that I can now attach this to a multitude of objects but manually customize different prefabs with the same script. This I unfortunately tested in my IRIS game project as I was working on this on a break and as the Virtual project is more procedural based but I feel like this is definitely a useful tool. I will need to test accessing and adding it to Gameobjects in game time to see if it's stable for that purpose before I start using it standard.
A serialized class and Scriptable Object List, the standard class can be edited while the scriptable can only be referenced. |
MonoBehaviour and contained data classes for editor above |
Wednesday, November 21, 2018
Unity Virtual Project: Progress 1
November 21, 2018
I had some trouble getting started on a concept for my Unity project, what I did is I went back to my project IRIS which is my game project I started in late August after attempting several other objects. I found just spending an hour in it let me readjust to Unity's editor. I spent time cleaning up code but more importantly it let me test things like serialized fields and using standard classes as well I learned a bit about graphics and custom editor scripts and to be more specific I learned about how much I wasn't ready to take on that level of coding. The feature I tried cleaning up was an upgrade system where I can simply build a object that modifies the player and by adding that game object to a reference it applies that ability to that player such as boots that can add in air movement and double jumping, I also had to adjust my movement code that would linearly control velocity for one that uses the physics and acceleration as that would be more open to further upgrading down the line.
After getting readjusted I decided that it would be a good idea to start building things that are simple but unique to experience such as water and buoyancy, right now that exists as a static cube with a trigger collider that applies upward force on any object that enters it's trigger. It is possible to make buoyancy based on density but Unity's transform only measures size from the base model, I havent been able to find any documentation that can give me the volume of a mesh for the calculations.
The next component I want to work on comes from my game project IRIS where I wanted to develop a character that's a conglomerate of consciousnesses as a networked organism, this would be easy narratively but my stretch goal is to have a form of city sim for the player to explore and this networked organism could move and shift through the city's system growing and changing behaviour (like I said, it's a stretch goal). I thought this project would be a good opportunity to prototype that concept. My language midterm was able to collect and network words based on how the user responds, with Unity I can take advantage of it's GameObject system and skip a lot of the week of work I did just getting Processing to produce and display multiple instances of Objects. Right now Im working for a gameObject call BioMass to search for node by shooting out rayCasts or sphereCasts in random directions like a snake tongue waving back and forth looking for Resource Node Gameobjects and adding a duplicate of itself to it's direction. I hope to later develop this in ways such as passing information through the connected parts or developing new types of Biomass objects based on growing conditions. I have a few ideas of how to do this but what I really want to see if there's any viable self learning programming for Unity that's comprehensive enough for someone at my skill to make use of.
Here's a screenshot of the first test, everything crashed so Im not doing that again. It's ironic that in my first attempt it duplicated so fast Unity bottlenecked, hope I dont destroy humanity or anything.
I had some trouble getting started on a concept for my Unity project, what I did is I went back to my project IRIS which is my game project I started in late August after attempting several other objects. I found just spending an hour in it let me readjust to Unity's editor. I spent time cleaning up code but more importantly it let me test things like serialized fields and using standard classes as well I learned a bit about graphics and custom editor scripts and to be more specific I learned about how much I wasn't ready to take on that level of coding. The feature I tried cleaning up was an upgrade system where I can simply build a object that modifies the player and by adding that game object to a reference it applies that ability to that player such as boots that can add in air movement and double jumping, I also had to adjust my movement code that would linearly control velocity for one that uses the physics and acceleration as that would be more open to further upgrading down the line.
After getting readjusted I decided that it would be a good idea to start building things that are simple but unique to experience such as water and buoyancy, right now that exists as a static cube with a trigger collider that applies upward force on any object that enters it's trigger. It is possible to make buoyancy based on density but Unity's transform only measures size from the base model, I havent been able to find any documentation that can give me the volume of a mesh for the calculations.
The next component I want to work on comes from my game project IRIS where I wanted to develop a character that's a conglomerate of consciousnesses as a networked organism, this would be easy narratively but my stretch goal is to have a form of city sim for the player to explore and this networked organism could move and shift through the city's system growing and changing behaviour (like I said, it's a stretch goal). I thought this project would be a good opportunity to prototype that concept. My language midterm was able to collect and network words based on how the user responds, with Unity I can take advantage of it's GameObject system and skip a lot of the week of work I did just getting Processing to produce and display multiple instances of Objects. Right now Im working for a gameObject call BioMass to search for node by shooting out rayCasts or sphereCasts in random directions like a snake tongue waving back and forth looking for Resource Node Gameobjects and adding a duplicate of itself to it's direction. I hope to later develop this in ways such as passing information through the connected parts or developing new types of Biomass objects based on growing conditions. I have a few ideas of how to do this but what I really want to see if there's any viable self learning programming for Unity that's comprehensive enough for someone at my skill to make use of.
Wednesday, November 14, 2018
Unity First Project
For our first project the outline was to create a Rube Goldberg machine built INSIDE Unity's physics engine. I've been pretty burnt out from midterms but I made some effort to dig around in the Unity manual and on forums to at least say I have been researching new things outside of what I know even if I didnt end up using them.
One feature I focused on was scene transitions using trigger objects to change the location and position of the camera. I did this by making a bunch of empty Gameobjects in the editor and storing them in a list on a script in the camera along with a list of trigger objects. Each trigger object also stored another object in a script that would make a boolean true when only both objects collide. The empty objects in the camera were named CameraAnchor (x) where whenever I duplicated an object x would increase representing each clone created, I used this feature in the script so that it automatically adds each duplicate to the list with a loop increasing x until it cant find anymore duplicates. Since the trigger objects were all named differently I had to manually insert them by making the list public, then I made another list of the Trigger script that referenced each script inside the object to get the bools, I did this so that I can manipulate the trigger script list without worrying about resetting the trigger object list. Then I made a for loop that would check if any of the trigger scripts outputs true and when it did I the camera move to the next duplicate and remove that trigger script from the list so it cant return true twice. I made the camera progress to the next object by using the list the CameraAnchors are stored in and simply increasing the int in the array reference every time it got a true boolean.
oh and I made the see saws by slapping a HingeJoint component on the objects and unless you set a parent rigidbody for it to hang on it just pivots in the air by default which was pretty straightforward.
I didn't have a .obj file from the OBDF class but I had this Donut I was making to learn Blender with, it's not a closed mesh so it causes major problems and crashes but I managed to make it work with the mesh collider by using the basic inflated vertex setting and exporting it without all the subdivision smoothing effects.
One feature I focused on was scene transitions using trigger objects to change the location and position of the camera. I did this by making a bunch of empty Gameobjects in the editor and storing them in a list on a script in the camera along with a list of trigger objects. Each trigger object also stored another object in a script that would make a boolean true when only both objects collide. The empty objects in the camera were named CameraAnchor (x) where whenever I duplicated an object x would increase representing each clone created, I used this feature in the script so that it automatically adds each duplicate to the list with a loop increasing x until it cant find anymore duplicates. Since the trigger objects were all named differently I had to manually insert them by making the list public, then I made another list of the Trigger script that referenced each script inside the object to get the bools, I did this so that I can manipulate the trigger script list without worrying about resetting the trigger object list. Then I made a for loop that would check if any of the trigger scripts outputs true and when it did I the camera move to the next duplicate and remove that trigger script from the list so it cant return true twice. I made the camera progress to the next object by using the list the CameraAnchors are stored in and simply increasing the int in the array reference every time it got a true boolean.
oh and I made the see saws by slapping a HingeJoint component on the objects and unless you set a parent rigidbody for it to hang on it just pivots in the air by default which was pretty straightforward.
I didn't have a .obj file from the OBDF class but I had this Donut I was making to learn Blender with, it's not a closed mesh so it causes major problems and crashes but I managed to make it work with the mesh collider by using the basic inflated vertex setting and exporting it without all the subdivision smoothing effects.
Wednesday, November 7, 2018
Midterm Done
So the program works really well aside from some minor glitches. I was able to successfully produce words, produce sentences, and assemble words based on their assigned function in English syntax. This post is a bit late as I was having some last minute issues with the sentence constructor as well as issues with screen capturing as I was running it in fullscreen initially.
What is being shown is the program creates a set of words with random function being nouns or verbs. These are represented as the coloured dots on screen. The blue line shows which words are being used in the current sentence. If you select a positive response the words will then have a green line and recorded as complimentary so that the sentence constructor will attempt to add those words together in other sentences as they make sense in context (according to player response). If a negative response is selected the words will be given a red line to show a dead relation and the program will avoid using those words together in a sentence however new words may connect the two as a new word may change the context of the statement. The "I understand" and "pointless" options are there to increase the rate the words generate if the statements start becoming repetitious or aren't readable.
I wasn't able to touch any of the AI concepts since that would have been a project in itself but I think I'm happy having a networking language program that as far as I'm concerned shouldn't crash given the stress testing I've done. I was hoping to add some more graphics to the project like towers to show an archive of all the sentences as well as adding more sentences each cycle however at the current state I would have to move a lot of code around and Im unfortunately out of time. I'm struggling to go back and comment all of the code but I did leave some variables in that I wasnt able to utilize in the final build. Those however I left in so I had some room to expand if I did end up having the time.
//CODE
PVector[] snowFlakes = new PVector[2000];
float[] snowSpin = new float[2000];
Entity player = new Entity();
Entity stranger = new Entity();
Words useWords = new Words();
Central central = new Central();
int progress = 0;
void setup()
{
size(1600, 900, P3D);
//fullScreen(P3D);
snowSetup();
//pWords.makeWord();
//pWords.makeWord();
for (int a = 0; a < 5; a++)
{
central.addWord();
}
player.addDialogue("Yes");
player.addDialogue("No");
player.addDialogue("I think I understand");//pWords.wordList.get(0));
player.addDialogue("This is pointless");//pWords.wordList.get(1));
}
void draw()
{
lights();
translate(0, 0, 0);
background(200);
midGround();
snowing();
timeLine();
playerSpeak();
central.drawMe();
}
void snowSetup()
{
for (int a = 0; a < snowFlakes.length; a ++)
{
snowSpin[a] = random(-1, 1);
snowFlakes[a] = new PVector(random(-width, width*2), random(-height/2, height), random(-width*2, width*.75));
}
}
void snowing()
{
noStroke();
fill(255, 255, 255, 200);
for (int a = 0; a < snowFlakes.length; a ++)
{
pushMatrix();
translate(snowFlakes[a].x, snowFlakes[a].y, snowFlakes[a].z);
//ellipse(0, 0, 10, 5);
rect(0, 0, 20, 10);
popMatrix();
//random variation in snowing movement
snowSpin[a] += random(-.2, .1);
//wave movement with y set to always increase
snowFlakes[a].y += abs(sin(snowSpin[a]));//random(0.1,1);
snowFlakes[a].x += cos(snowSpin[a])/2;//random(-.5,.5);
snowFlakes[a].z += cos(snowSpin[a])/2;
//reset the snow position to the sky once it hits the ground
if (snowFlakes[a].y > height)
{
snowFlakes[a] = new PVector(random(-width, width*2), random(-height, -height/2), random(-width*2, width*.75));
}
}
}
void midGround()
{
stroke(100);
fill(150, 100, 100);
pushMatrix();
translate(width/2, height+100, -width/2);
box(width*10, 100, width*10);
popMatrix();
}
void playerSpeak()
{
if (stranger.doneTalking())
{
player.multipleText();
}
}
void timeLine()
{
switch(progress)
{
case 0:
//reset sentences
stranger.dialogue = new ArrayList();
//stranger.addDialogue("Busy working on the " + sWords.wordList.get(0) + "?");
stranger.addDialogue(central.makeSentence());
stranger.setupText();
progress++;
central.addWord();
break;
case 1:
stranger.textBox();
central.remember();
break;
}
}
//a String based Dictionary class for holding 1 string as a word and it's traits
class Dict
{
ArrayList <String> wordList = new ArrayList();
String word;
//other words that has made a positive response
ArrayList <Dict> siblings = new ArrayList();
//other words that has made a negative response
ArrayList <Dict> rejects = new ArrayList();
boolean isPronoun;
boolean isPropNoun;
boolean isNoun;
boolean isVerb;
boolean isAdjective;
boolean isAdverb;
boolean isSpecific;
boolean isGeneral;
//drawing
PVector dColour = new PVector();
PVector outPos = new PVector();
PVector moveRate = new PVector();
float rotation;
float orbitOff;
//
float orbitR;
Dict(String eWord)
{
word = eWord;
//
rotation = random(-2, 1);
//
orbitOff = random(-1, 1);
orbitR = central.definitions.size();
//
dColour = new PVector(random(0,255),random(0,255),random(0,255));
}
//use this to assign a word to either verb or noun randomly
void randomTraits()
{
//rolls a random float between 0 and 2 and rounds down to an int
//0 = false, anything above zero (1 or 2) is true;
if (boolean(floor(random(0, 2))))
{
println("noun");
isNoun = true;
if (boolean(floor(random(0, 2))))
{
isSpecific = true;
} else
{
isGeneral = true;
}
} else
{
println("verb");
isVerb = true;
}
}
//draw
void moveDot()
{
rotation += random(0, 0.005);
orbitOff += random(0, 0.012);
moveRate.x = sin(rotation);
moveRate.y = cos(orbitOff);
moveRate.z = cos(rotation);
moveRate = moveRate.normalize();
outPos.x = width/2 + moveRate.x * (orbitR + 200);
outPos.y = height/2 + moveRate.y * (orbitR + 200);
outPos.z = -width/2 + moveRate.z * (orbitR + 200);
}
}
class Central
{
int positive;
int negative;
PVector centerPos;
ArrayList <String> sentences = new ArrayList();
ArrayList <Dict> definitions = new ArrayList();
//Definite articles refer to the subject
String the = "the";
//Indefinite Articles refer to a subject
String aaa = "a";
ArrayList <Dict> phraseWords = new ArrayList();
String phrase;
int wordCountP;
int sentCount;
int hasSiblings;
//
Central()
{
}
//use to construct a new word with random traits
void addWord()
{
definitions.add(new Dict(useWords.makeWord()));
definitions.get(definitions.size()-1).randomTraits();
}
//Make a sentence
String makeSentence()
{
hasSiblings = 0;
//reset variables
wordCountP = int(random(2, 4));
phraseWords = new ArrayList();
phrase = new String();
//add a random word for the array size
for (phraseWords.size(); phraseWords.size() < wordCountP; )
{
phraseWords.add(definitions.get(int(random(0, definitions.size()))));
//add a sibling
if (phraseWords.get(phraseWords.size()-1).siblings.size()>0)
{
phraseWords.add(phraseWords.get(phraseWords.size()-1)
.siblings.get(int(random(0, phraseWords.get(phraseWords.size()-1).siblings.size()-1))));
}
//remove a reject
for (int a = 1; a < phraseWords.size(); a++)
{
//for (int b = 0; b < phraseWords.size(); b++)
{
if (phraseWords.get(a).rejects.size()>0)
{
for (int c = 0; c < phraseWords.get(a).rejects.size(); c++)
{
if (phraseWords.get(a).rejects.get(c) == phraseWords.get(a-1))
{
if (a >= phraseWords.size())
{
phraseWords.remove(a-1);
}
}
}
}
}
}
}
//Sentence construction
for (int a = 0; a < phraseWords.size(); a++)
{
//add a conjunction between subjects
if (a> 0 && a+1 < phraseWords.size())
{
if (phraseWords.get(a).isNoun && phraseWords.get(a+1).isNoun)
{
phrase += "and ";
}
}
//Add definite article before noun.
if (phraseWords.get(a).isNoun)
{
//use the construct method to add an Article
//add "the" to a known subject
phrase += article(phraseWords.get(a).isSpecific, the + " ", a);
//add "a" to a general subject
phrase += article(phraseWords.get(a).isGeneral, aaa + " ", a);
}
//add a new word.
phrase+= phraseWords.get(a).word;
//add space if there are still words to add.
if (a < phraseWords.size()-1)
{
phrase += " ";
}
}
//if there are 2 verbs together then the last becomes an adverb.
if (phraseWords.get(phraseWords.size()-1).isVerb && phraseWords.get(phraseWords.size()-2).isVerb)
{
phrase+= "ly";
}
phrase+= ".";
return phrase;
}
//recieve viewer feedback
void remember()
{
if (player.pInput[0])
{
positive++;
progress = 0;
for (int a = 1; a < phraseWords.size(); a++)
{
phraseWords.get(a).siblings.add(phraseWords.get(a-1));
}
}
if (player.pInput[1])
{
positive--;
progress = 0;
for (int a = 1; a < phraseWords.size(); a++)
{
phraseWords.get(a).rejects.add(phraseWords.get(a-1));
}
}
if (player.pInput[2])
{
positive+=2;
progress = 0;
for (int a = 1; a < phraseWords.size(); a++)
{
phraseWords.get(a).siblings.add(phraseWords.get(a-1));
}
addWord();
addWord();
}
if (player.pInput[3])
{
positive-=3;
progress = 0;
for (int a = 1; a < phraseWords.size(); a++)
{
phraseWords.get(a).rejects.add(phraseWords.get(a-1));
}
addWord();
addWord();
}
}
//returns a string that is a verb
String verb()
{
//only run loop if dictionary contains a word
if (definitions.size()>0)
{
//grab a random word from the dictionary
for (int a = 0; a < definitions.size(); a = int(random(0, definitions.size()))) //definitions.get(a).isVerb; a ++)
{
//check if the word is a verb to output
if (definitions.get(a).isVerb)
{
return definitions.get(a).word;
}
}
}
return "";
}
String article(boolean trait, String word, int wordPlace)
{
if (trait)
{
if (wordPlace == 0)
{
return word.substring(0, 1).toUpperCase() + word.substring(1, word.length());
} else
{
return word;
}
}
return "";
}
//Returns a Noun
String noun()
{
//only run if the dictionary contains a word
if (definitions.size()>0)
{
//grab a random word from the dictionary
for (int a = 0; a < definitions.size(); a = int(random(0, definitions.size()))) //definitions.get(a).isVerb; a ++)
{
//check if the word is a noun
if (definitions.get(a).isNoun)
{
return definitions.get(a).word;
}
}
}
return "";
}
String ranWord()
{
return definitions.get(int(random(0, definitions.size()))).word;
}
//display the words
void drawMe()
{
centerPos = new PVector(width/2, height/2, -width/2);
//draw center
pushMatrix();
translate(centerPos.x, centerPos.y, centerPos.z);
fill(250, 100, 200);
ellipse(0, 0, 100, 100);
popMatrix();
//draw orbits
fill(200, 150, 150);
for (int a = 0; a < definitions.size(); a ++)
{
fill(definitions.get(a).dColour.x, definitions.get(a).dColour.y, definitions.get(a).dColour.z);
pushMatrix();
definitions.get(a).moveDot();
translate(definitions.get(a).outPos.x, definitions.get(a).outPos.y, definitions.get(a).outPos.z);//a*50, defPos.get(a).y);
ellipse(0, 0, 50, 50);
popMatrix();
}
//active connections
strokeWeight(10);
stroke(100, 100, 200, 200);
for (int a = 1; a < phraseWords.size(); a++)
{
line(phraseWords.get(a).outPos.x, phraseWords.get(a).outPos.y, phraseWords.get(a).outPos.z - 5,
phraseWords.get(a-1).outPos.x, phraseWords.get(a-1).outPos.y, phraseWords.get(a-1).outPos.z - 5);
}
//sibling connections
strokeWeight(8);
stroke(150, 170, 50, 125);
for (int a = 1; a < definitions.size(); a++)
{
for (int b = 0; b < definitions.get(a).siblings.size(); b++)
{
line(definitions.get(a).outPos.x, definitions.get(a).outPos.y, definitions.get(a).outPos.z - 10,
definitions.get(a).siblings.get(b).outPos.x, definitions.get(a).siblings.get(b).outPos.y,
definitions.get(a).siblings.get(b).outPos.z - 10);
}
}
//reject connections
strokeWeight(8);
stroke(120, 50, 50, 125);
for (int a = 1; a < definitions.size(); a++)
{
for (int b = 0; b < definitions.get(a).rejects.size(); b++)
{
line(definitions.get(a).outPos.x, definitions.get(a).outPos.y, definitions.get(a).outPos.z - 10,
definitions.get(a).rejects.get(b).outPos.x, definitions.get(a).rejects.get(b).outPos.y,
definitions.get(a).rejects.get(b).outPos.z - 10);
}
}
}
}
//a String based Dictionary class for holding 1 string as a word and it's traits
class Dict
{
ArrayList <String> wordList = new ArrayList();
String word;
//other words that has made a positive response
ArrayList <Dict> siblings = new ArrayList();
//other words that has made a negative response
ArrayList <Dict> rejects = new ArrayList();
//boolean isPronoun;
//boolean isPropNoun;
boolean isNoun;
boolean isVerb;
//boolean isAdjective;
//boolean isAdverb;
boolean isSpecific;
boolean isGeneral;
//drawing
PVector dColour = new PVector();
PVector outPos = new PVector();
PVector moveRate = new PVector();
float rotation;
float orbitOff;
//
float orbitR;
Dict(String eWord)
{
word = eWord;
//
rotation = random(-2, 1);
//
orbitOff = random(-1, 1);
orbitR = central.definitions.size();
//
dColour = new PVector(random(0,255),random(0,255),random(0,255));
}
//use this to assign a word to either verb or noun randomly
void randomTraits()
{
//rolls a random float between 0 and 2 and rounds down to an int
//0 = false, anything above zero (1 or 2) is true;
if (boolean(floor(random(0, 2))))
{
println("noun");
isNoun = true;
if (boolean(floor(random(0, 2))))
{
isSpecific = true;
} else
{
isGeneral = true;
}
} else
{
println("verb");
isVerb = true;
}
}
//draw
void moveDot()
{
rotation += random(0, 0.005);
orbitOff += random(0, 0.012);
moveRate.x = sin(rotation);
moveRate.y = cos(orbitOff);
moveRate.z = cos(rotation);
moveRate = moveRate.normalize();
outPos.x = width/2 + moveRate.x * (orbitR + 200);
outPos.y = height/2 + moveRate.y * (orbitR + 200);
outPos.z = -width/2 + moveRate.z * (orbitR + 200);
}
}
class Entity
{
PVector position = new PVector();
//Text
//Speech list
ArrayList <String> dialogue = new ArrayList();
//
int dStep = 0;
//
float printSize = 30;
//Text box
PVector tbSize = new PVector(300, 100);
PVector tbPos = new PVector();
//printing speed
float textSpeed;
//print line
int step = 1;
//the width of each row
int lineLength = 30;
//the numbers of rows needed to print all the text
int textLineCount;
//counts up to print the text
int[] textCrawl = new int[4];
//the margins to start and stop the string segments
int[] textMargin = new int[5];
//locks each line of text to stop them from printing past the margins
boolean[] stepLocked = new boolean[4];
//
PVector tbButtonPos = new PVector();
PVector tbButtonSize = new PVector(50, 50);
//
boolean textDone;
boolean pressLock;
Entity()
{
}
void addDialogue(String enterText)
{
//enter dialogue string;
dialogue.add(enterText);
}
//sets up all the parameters for the dialogue box to display and print;
void setupText()
{
//measure the amount of rows needed to draw all the text
textLineCount = ceil(dialogue.get(dStep).length()/lineLength)+1;
//set Textbox position
tbPos = new PVector(width - lineLength*12 - 300, height/2 + 50);
//set the textbox size to encapsulate all the text
tbSize = new PVector(lineLength*12 + 100, textLineCount * (printSize));
//println(textLineCount);
//reinitialize all the arrays to the correct size to print all the dialogue
//text printing
textCrawl = new int[textLineCount];
//stop each row from going over
stepLocked = new boolean[textLineCount];
//set the margin to stop and start the text in
textMargin = new int[textLineCount+1];
//setup margins for the text
for (int a = 0; a < textMargin.length; a ++)
{
//set the markers for when to start and end the text scrawl
textMargin[a] = lineLength*a;//tbSize.x/11)*a;
}
//setup the text typing starting positions;
for (int a = 0; a < textCrawl.length; a ++)
{
//set up an int to print in each letter as it increases;
textCrawl[a] = textMargin[a];
}
step = 1;
textSpeed = 0;
}
boolean doneAll;
//prints and proceeds dialogue on screen
void textBox()
{
pushMatrix();
//draw textBox
translate(tbPos.x, tbPos.y);
fill(230);
rect(0, 0, tbSize.x + 100, tbSize.y+10);
//text box
fill(0);
textSize(printSize);
translate(0, 30, 0);
//speed that the text will display at
textSpeed += 10/frameRate;
//print all lines of text out in the current dialogue string
for (int a = 0; a < step; a ++)
{
//stop the text from going beyond the string length and crashing
if (textCrawl[a] < dialogue.get(dStep).length())
{
//print text by increasing text lines until it hits the margin and dont cut the word off
if (textCrawl[a] < textMargin[a+1] || dialogue.get(dStep).charAt(textCrawl[a]) != ' ')
{
//dont print over dialogue length and crash
if (textCrawl[a] < dialogue.get(dStep).length())
{
//extend text print by the print speed;
textCrawl[a] = int(textSpeed);
}
}
}
//stop the text from going beyond dialogue length
if (textCrawl[a] < dialogue.get(dStep).length())
{
//if the text length is larger than the margin length start the next line
if (textCrawl[a] >= textMargin[a+1] )//&& dialogue.get(0).charAt(textCrawl[a]) == ' ')
{
//only move to the next line once;
if (!stepLocked[a])
{
//only move down a line if there is another line and dont cut words off
if (step+1 <= textCrawl.length && (dialogue.get(dStep).charAt(textCrawl[a]) == ' ' || dialogue.get(dStep).charAt(textCrawl[a]) == '.'))
{
//move the starting marker to where the previous line ended
textMargin[a+1] = textCrawl[a];
//lock this line of text
stepLocked[a] = true;
//increase loop size to add the next text line;
step++;
}
}
}
}
//Text
fill(100, 100, 255);
//println(textMargin[a] + " " + textCrawl[a]);
text(dialogue.get(dStep).substring(textMargin[a], textCrawl[a]), 10, 25*a);
}
//textCrawl[0] = int(textSpeed);
popMatrix();
//Return true once all the text in the current line of dialogue is done printing
textDone = true;
if (textCrawl[textCrawl.length-1] < dialogue.get(dStep).length())
{
//println(dialogue.get(0).length());
textDone = false;
}
//load the button to proceed to the next dialogue;
if (textDone)
{
nextTextButton();
}
}
//proceeds text to next lines
void nextTextButton()
{
tbButtonPos = new PVector(tbPos.x, tbPos.y);
tbButtonPos.x = tbPos.x + tbSize.x - tbButtonSize.x;
tbButtonPos.y = tbPos.y + tbSize.y;
if (dStep+1 < dialogue.size()) {
//select to progress dialogue when first line is done.
if (mouseX > tbButtonPos.x && mouseX < tbButtonPos.x + tbButtonSize.x)
{
if (mouseY > tbButtonPos.y && mouseY < tbButtonPos.y + tbButtonSize.y)
{
if (mousePressed)
{
//dont proceed if it's the end of text list
if (pressLock)
{
dStep ++;
setupText();
pressLock = false;
}
//println(true);
} else
{
pressLock = true;
}
}
}
}
pushMatrix();
fill(50);
translate(tbButtonPos.x, tbButtonPos.y);
rect(0, 0, tbButtonSize.x, tbButtonSize.y);
popMatrix();
}
//tells the program when the current dialogue has run through
boolean doneTalking()
{
if (dStep+1 >= dialogue.size() && textDone)
{
return true;
}
return false;
}
PVector pPos = new PVector(100, 200);
boolean[] pInput = new boolean[4];
PVector rPos;
PVector rEnd;
void multipleText()
{
pushMatrix();
//make a return for each response option
pInput = new boolean[dialogue.size()];
//draw all the player choices
for (int a = 0; a < dialogue.size(); a++)
{
//positions and size
rPos = new PVector(100, 200 + 60*a);
rEnd = new PVector(20 + (printSize/2*dialogue.get(a).length()), 50);
//draw the rectangles
fill(150, 150, 50);
rect(rPos.x, rPos.y, 20 + rEnd.x, rEnd.y);
//draw the text
fill(50, 50, 50);
textSize(printSize);
text(dialogue.get(a), pPos.x + 10, pPos.y + 30 + 60*a);
//Player input when they select a dialogue
if (mouseX > rPos.x && mouseX < rPos.x + rEnd.x)
{
if (mouseY > rPos.y && mouseY < rPos.y + rEnd.y)
{
if (mousePressed)
{
if (dStep+1 < dialogue.size() && pressLock)
{
pInput[a] = true;
println(true);
pressLock = false;
}
//println(true);
} else
{
pressLock = true;
}
}
}
}
popMatrix();
}
}
class Words
{
//String[] vowels = {"a", "e", "i", "o", "u"};
char[] vowels = {'a', 'e', 'i', 'o', 'u'};
//String[] cons = {"b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z"};
char[] cons = {'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'};
String[] anyLetter = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
"k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"};
//char[] anyLetter = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
//'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
ArrayList <String> wordList = new ArrayList();
String word;
ArrayList <String> siblings = new ArrayList();
ArrayList <String> rejects = new ArrayList();
Words(String eWord)
{
word = eWord;
}
Words()
{
}
//String word = new String();
int wordLength;
boolean addDone;
//THIS function generates new words and adds them to the stack whenever it's called
String makeWord()
{
wordLength = int(random(1, 8));
//wordLength = 8;
word = new String();
for (int a = 0; a < wordLength; a++)
{
addDone = false;
if (word.length() <= 0)
{
word += new String(anyLetter[int(random(0, anyLetter.length))]);
}
if (word.length() > 0)
{
//check if last letter is any vowel
for (int b = 0; b < vowels.length; b ++)
{
if (!addDone)
{
//add constinent if last letter is vowel
if (word.charAt(word.length()-1) == vowels[b])
{
word += cons[int(random(0, cons.length))];
addDone = true;
}
}
}
//check if last letter is a constinant
for (int b = 0; b < cons.length; b ++)
{
if (!addDone)
{
//add vowel if last letter is constinant
if (word.charAt(word.length()-1) == cons[b])
{
word += vowels[int(random(0, vowels.length))];
addDone = true;
}
}
}
}
}
wordList.add(word);
return word;
}
String lateWord()
{
return(wordList.get(wordList.size()-1));
}
}
Wednesday, October 31, 2018
Midterm Update 1
After reviewing the each other's proposals I had a really good exchange with Kyle where he mentioned a site called the Library of Babel which is based on the book of the same name which does something along the line of generating every line of characters possible in theory and bookmarking it. I thought it was an interesting idea to try and wrap my project around language in that sense.
My original project was more story based an honestly I've never touched a self automated system before in coding so it's all new territory so I have little estimate on how feasible it is. As it is now I still want the program to proceed through a narrative instead of stagnating on a single scene, it's a minor but significant detail as currently I'm focusing on forming the basic functions for producing language.
This whole line of thinking is really stretching my definition of will and when a mass of conflicting goals starts producing compromises and behavior. It has me remembering the animated film Ghost in the Shell (1995) that I unfortunately lent to a friend prior to the project but the thesis of the film was how a mass of information and instructions eventually produces a conflicted self determined system.
What I have currently working in my project is dialogue class that can print itself out as well as generating words that vary consonants and vowels to at least be readable for English speakers. Part of that class allows me to generate a selection of words that the viewer can respond with. I'm currently moving onto developing an actual class to store and respond to the words.
Currently I'm still planning on using bacteria as the archetype for positive and negative responses as well as setting basic goals for the program such as constructing new strings and using words together to build context as primitive sentences. My current workflow can be seen as this:
My original project was more story based an honestly I've never touched a self automated system before in coding so it's all new territory so I have little estimate on how feasible it is. As it is now I still want the program to proceed through a narrative instead of stagnating on a single scene, it's a minor but significant detail as currently I'm focusing on forming the basic functions for producing language.
This whole line of thinking is really stretching my definition of will and when a mass of conflicting goals starts producing compromises and behavior. It has me remembering the animated film Ghost in the Shell (1995) that I unfortunately lent to a friend prior to the project but the thesis of the film was how a mass of information and instructions eventually produces a conflicted self determined system.
What I have currently working in my project is dialogue class that can print itself out as well as generating words that vary consonants and vowels to at least be readable for English speakers. Part of that class allows me to generate a selection of words that the viewer can respond with. I'm currently moving onto developing an actual class to store and respond to the words.
Currently I'm still planning on using bacteria as the archetype for positive and negative responses as well as setting basic goals for the program such as constructing new strings and using words together to build context as primitive sentences. My current workflow can be seen as this:
- Create words and output them.
- Memorize words and viewer's response.
- Sort words based on if the response is negative or positive
- Attach words to the context of nouns or verbs that respond positive or negative when connected
- Output a new response by attaching words with connected meaning.
As of today I'm currently on step 2 however coding the next steps should not be a lot of code but simple modules of looping code that need to fit into each-other. I'm going to give myself until Monday to finish this behaviour to make sure I don't sink all my time into overdeveloping a single piece of the project. If I don't complete it I'm confident even a basic primitive function will work to complete the project.
Wednesday, October 24, 2018
Midterm Project
Digital art has the benefit of interactivity and commercially they're labeled video games but I have my gripes for how formulaic it is. As it sits video games are more resembling of a sport or a toy, there's few of them that hold a narrative or artistic intent while they remain focused on entertainment value. There was one game director name Yoko Taro who in short is know for making mostly bad games with good stories, one of the talks he did he said that what he found was important about video games was the medium of interactivity as unique to games and the focus for giving the player an experience. I think his idea around game design and AI is close to paralleling the reading we were given for the project where different artists end up focusing on different parts of computer generated graphics like biology, behavior, mathematics but in the end the emerging technology is always open to new inventive artistic expressions.
For my project I want to focus on building a meaningful action into what the viewer decides to do. I want to act as a short story that responds to the audience. As the viewer gets deeper into the story I want to implement more of the Artificial Life ideas in the reading to shift the tone from a prescripted story to a more organic self active system, one that can agree and disagree based on the information it gets from you.
This type of response came to me when I thought of how the reading described Artificial Life (A-Life) characters in novels are nothing more than words on paper and at most internalized personalities but in code characters function inside a the computer through the transfer of information, it made me think about what the difference is between a Roomba vacuum using walls to navigate a carpet and a bacteria chasing a tasty chemical scent. To be more specific if I built boolean that was called pleasure and one called pain is turning them on and off different than the pain and pleasure an insect feels? Sure there is evolution and life but the what we describe as self has more to do with information and navigating the best from the worst. I think even in a barebones form I would like to attempt to include this idea into my story.
What I want to do through dialogue is closer to a novel where the character is more the words I've printed being imagined as a person but I think that along with some surreal graphics I can invest the viewer into making meaningful choices even if it's just an illusion.
For this project Im very confident in utilizing classes and for loops which is what the dialogue printing in this earlier test video relies on. I've used the substring function to take slices of the string and print them out in paragraph form, the working version moves to the next line of text on a button as well it waits for me to add more text which is essential to adding events between scenes. For the meantime Im limiting myself to focus on fleshing out the story in text form before adding visuals and then more interactivity like after declaring your character has done an action it cuts to the viewer acting out that action with interactions. I've set up my workflow as such because I know the workload can become very bloated when it comes to manually writing events instead of relying solely on looping code so I want to build it in stages that prioritize the writing and then adds in additional elements with remaining time.
I havent decided entirely on the assets yet however Im currently relying on processing to produce graphics since that allows me to control more organic effects I think once I get further in I can be confident in applying them without worrying about aesthetic consistency.
Wednesday, October 10, 2018
Processing Classes Practice
Can be played here: https://www.openprocessing.org/sketch/605087
CODE:
//MAIN
//empty vector for using Vector functions
Vector useVector = new Vector();
Entity useEntity = new Entity(0);
//empty collision for using collision functions
//player Object
Entity player;//movement input
char[] moveKeys = {'d', 'a', 'w', 's'};
//movement values
int[] moveValues = new int[4];
//movement Vector
Vector moveVector = new Vector();
//movement Velocity
Vector moveVelocity = new Vector();
float playerSpeed = 5;
//Game Timeline
boolean startGame = false;
float gameTime;
//playerAttack
//bulletList
ArrayList <Bullet> bulletStack;
Vector playerBSpawn;
boolean attackPress;
float attackPause = 8;
float attackCycle;
//Enemies
Entity dummy;
//Enemy List
ArrayList <Entity> enemyList;
//enemy bulletList
ArrayList <Bullet> EBulletStack;
//Enemy Sequence
int ESequence;
void setup()
{
size(1080, 720);
//all colliders will be based on radius from the center of objects
rectMode(CENTER);
//set bullet stack to an empty ArrayList
bulletStack = new ArrayList();
//start position of the player
player = new Entity(40, new Vector(width/2, height/1.2));
//Enemies
EBulletStack = new ArrayList();
//
enemyList = new ArrayList();
//enemyList.add(dummy);
//enemy Setup
enemyTypes();
}
void draw()
{
//background(255, 240, 200);
fill(255, 240, 200, 150);
rect(width/2, height/2, width, height);
movePlayer();
drawBullet();
damageHit();
enemySequence();
}
//
void mousePressed()
{
attackPress = true;
}
void mouseReleased()
{
attackPress = false;
}
void keyPressed()
{
for (int a = 0; a < moveKeys.length; a++)
{
if (key == moveKeys[a])
{
moveValues[a] = 1;
}
if (key == ' ')
{
attackPress = true;
}
}
}
void keyReleased()
{
for (int a = 0; a < moveKeys.length; a++)
{
if (key == moveKeys[a])
{
moveValues[a] = 0;
}
if (key == ' ')
{
attackPress = false;
}
}
}
void movePlayer()
{
//direction input
moveVector = new Vector(moveValues[0]- moveValues[1], moveValues[3] - moveValues[2]);
moveVelocity = new Vector(moveVector.x * playerSpeed, moveVector.y * playerSpeed);
//apply movement
player.position = useVector.addVelocity(player.position, moveVelocity);
//playerAttack
//attack cooldown
if (attackCycle > 0)
{
attackCycle--;
}
//attack when the attack cooldown is back at 0
if (attackPress && attackCycle <= 0)
{
playerBSpawn = new Vector(player.position.x, player.position.y-35);
//create a new bullet
Bullet a = new Bullet(playerBSpawn, new Vector(0, -13));
bulletStack.add(a);
//start attack cooldown
attackCycle = attackPause;
}
//draw the player
player.drawCirc();
}
void drawBullet()
{
//according to google "for(class : Arraylist){}" checks for every class in a array of classes,
//useful but not my own work.
/*for(Bullet stack: bulletStack)
{
stack.drawBullet();
stack.moveBullet();
}*/
//move and draw each bullet in the stack
for (int a = 0; a < bulletStack.size(); a++)
{
fill(200,100,255);
bulletStack.get(a).moveBullet();
bulletStack.get(a).drawBullet();
//delete the bullet if it's out of bounds
if (bulletStack.get(a).deleteBullet())
{
bulletStack.remove(a);
}
}
}
//Damage
void damageHit()
{
//HIT ENEMIES
if (enemyList.size()>0)
{
for (int b = 0; b < enemyList.size(); b++)
{
//fix out of bounds bug
if (bulletStack.size()>0)
{
for (int a = 0; a < bulletStack.size(); a++)
{
//attack test
//use collision boolean method on bullets and target
if (useEntity.attackCollision(bulletStack.get(a), enemyList.get(b)))
{
bulletStack.remove(a);
}
}
}
//if enemy has health
if (enemyList.get(b).health > 0)
{
enemyList.get(b).drawCirc();
} else
{
enemyList.remove(b);
}
}
}
//PLAYER damage
if (EBulletStack.size() > 0)
{
for (int a = 0; a < EBulletStack.size(); a++)
{
//use collision boolean method on bullets and test dummy
if (useEntity.attackCollision(EBulletStack.get(a), player))
{
EBulletStack.remove(a);
}
}
}
}
boolean onEnemy;
//bugger type enemy
Entity bugger;
Entity skimmer;
Entity rusher;
Entity doozers;
void enemyTypes()
{
//
dummy = new Entity(100, new Vector (width/2, 100));
dummy.health = 25;
dummy.lifeSpan = -10;
dummy.moveSetup(new Vector(), 50, 20, .05);
//
bugger = new Entity(50, new Vector());
bugger.lifeSpan = 600;
//bugger.attackSetup(new Vector(0,3), 1);
bugger.attackSetup(new Vector(1,2), 1);
bugger.attackSetup(new Vector(-1,2), 1);
bugger.moveSetup(new Vector(0,1), 70,0, .05);
//
skimmer = new Entity(70, new Vector());
skimmer.health = 20;
skimmer.lifeSpan = 600;
skimmer.attackSetup(new Vector(2,2), 1);
skimmer.moveSetup(new Vector(2,0), 0,0,1);
//
rusher = new Entity(60, new Vector());
rusher.health = 5;
rusher.lifeSpan = 600;
rusher.attackSetup(new Vector(2,1), .5);
rusher.attackSetup(new Vector(-2,1), .5);
rusher.moveSetup(new Vector(0,3), 0,0,1);
//
doozers = new Entity(30, new Vector());
doozers.health = 3;
doozers.lifeSpan = 1200;
doozers.attackSetup(new Vector(1,1), 1.25);
doozers.attackSetup(new Vector(-1,1), 1.25);
doozers.attackSetup(new Vector(-1,-1), 1.25);
doozers.attackSetup(new Vector(1,-1), 1.25);
doozers.moveSetup(new Vector(0,.5),20,20,.1);
}
//the timeline for all enemy spawns
void enemySequence()
{
//a bool to stop if conditions from crashing if the enemy list is empty/null.
//must be first condition or array list will crash
if (enemyList.size() >0)
{
onEnemy = true;
} else
{
onEnemy = false;
}
//add enemies to the game on time when the game starts
switch(int(gameTime))
{
//create the starting enemy
/*case:
//add enemy
List.add(enemyObject);
//starting position
List.get(int).position = new Vector();
*/
case 0:
enemyList.add(dummy);
gameTime++;
break;
//start the game once starting enemy is destroyed
case 1:
if (!onEnemy)
startGame = true;
break;
case 2:
bugger.position = new Vector(width/2, -60);
enemyList.add(bugger);
gameTime++;
break;
case 6:
//must reset the classes to a new class(); to avoid double feedback
enemyTypes();
bugger.position = new Vector(width/2 + 100, -60);
enemyList.add(bugger);
//
enemyTypes();
bugger.position = new Vector(width/2 -100, -60);
enemyList.add(bugger);
gameTime++;
break;
case 15:
enemyTypes();
skimmer.position = new Vector(-50, 200);
enemyList.add(skimmer);
gameTime++;
break;
case 18:
enemyTypes();
skimmer.moveSetup(new Vector(-2,0), 0,0,-1);
skimmer.position = new Vector(width+50, 200);
skimmer.attackSetup(new Vector(-2,2), 1);
enemyList.add(skimmer);
gameTime++;
break;
case 25:
enemyTypes();
rusher.position = new Vector(width/2 - 300,-50);
enemyList.add(rusher);
//
enemyTypes();
rusher.position = new Vector(width/2 + 300,-50);
enemyList.add(rusher);
gameTime++;
break;
case 28:
enemyTypes();
doozers.position = new Vector(width/2 + 200, - 50);
enemyList.add(doozers);
//
enemyTypes();
doozers.position = new Vector(width/2, - 50);
enemyList.add(doozers);
//
enemyTypes();
doozers.position = new Vector(width/2 - 200, - 50);
enemyList.add(doozers);
//
enemyTypes();
doozers.position = new Vector(width/2 - 400, - 50);
enemyList.add(doozers);
//
enemyTypes();
doozers.position = new Vector(width/2 + 400, - 50);
enemyList.add(doozers);
gameTime++;
break;
}
//out of bounds check
if (onEnemy)
{
//all enemies
for (int a = 0; a < enemyList.size(); a++)
{
//move all enemies
enemyList.get(a).moveType();
enemyList.get(a).attackCycle();
//if the enemy has run out of time delete them
if(!enemyList.get(a).lifeTime())
{
enemyList.remove(a);
}
}
}
//keep bullet stack below limit by removing the last one in the stack
if (EBulletStack.size() > 200)
{
EBulletStack.remove(0);
}
//move and draw each bullet in the stack
for (int a = 0; a < EBulletStack.size(); a++)
{
fill(255,100,200);
EBulletStack.get(a).moveBullet();
EBulletStack.get(a).drawBullet();
//delete the bullet if it's out of bounds
if (EBulletStack.get(a).deleteBullet())
{
EBulletStack.remove(a);
}
}
//start game time
if (startGame)
{
//real seconds timer
gameTime += 1/frameRate;
//println(int(gameTime)+ " " + ESequence);
}
}
//BULLET CLASS
class Bullet
{
//empty Vector class for using class functions
Vector useVector = new Vector();
//bullet position
Vector bPos;
//bullet Size
float radius = 25;
//bullet Velocity
Vector bVelocity = new Vector();
//bullet lifeTime
float lifeTime = 1200;
//constructor for spawning the bullet in canvas space
Bullet(Vector position, Vector velocity)
{
bPos = position;
bVelocity = velocity;
}
//draw the bullet
void drawBullet()
{
noStroke();
ellipse(bPos.x, bPos.y,radius, radius);
}
//translate the bullet via it's velocity
void moveBullet()
{
bPos = useVector.addVelocity(bPos, bVelocity);
lifeTime -= 1;
}
//return true to delete bullet from arrayList
boolean deleteBullet()
{
if(lifeTime <= 0)
{
return true;
}
return false;
}
}
//ENTITY
class Entity
{
Bullet useBullet = new Bullet(new Vector(), new Vector());
float shape = 10;
Vector position = new Vector(0, 0);
//
float healthChange;
float health = 10;
//
float lifeSpan = 600;
//empty box with a shape
Entity(float a)
{
shape = a;
attackVectors = new ArrayList();
}
//shape and position
Entity(float a, Vector b)
{
shape = a;
position = b;
attackVectors = new ArrayList();
}
//
void drawCirc()
{
noStroke();
fill(200, 100, 100);
ellipse(position.x, position.y, shape+health, shape+health);
if (healthChange != health)
{
fill(255, 100, 100);
healthChange = health;
} else
{
fill(100, 100, 100);
}
stroke(0);
ellipse(position.x, position.y, shape, shape);
}
boolean attackCollision(Bullet bullet, Entity target)
{
if (dist(bullet.bPos.x, bullet.bPos.y, target.position.x, target.position.y) < bullet.radius/2 + target.shape/2)
{
//remove health from target on collision
target.health --;
return true;
}
return false;
}
boolean lifeTime()
{
//return true if object has time left
if (lifeSpan > 0)
{
return true;
}
//if lifespan is below 0 return false to delete enemy unless set below -10 for infinite lifetime;
if (lifeSpan > -10 && lifeSpan <=0)
{
return false;
}
//return true for infinite life
return true;
}
boolean mSetupOnce = false;
Vector velocity = new Vector();
float xMove;
float yMove;
float wSpeed;
//setup all entity movement on initiation;
void moveSetup(Vector lineMove, float xWave, float yWave, float waveSpeed)
{
//if (!mSetupOnce)
{
velocity = lineMove;
xMove = xWave;
yMove = yWave;
wSpeed= waveSpeed;
//mSetupOnce = true;
}
}
void moveType()
{
//if (xMove !=0 || yMove !=0 || wSpeed !=0)
{
sinMove(xMove, yMove, wSpeed);
}
///if (velocity.x != 0 || velocity.y != 0)
{
anchorPoint = useVector.addVelocity(anchorPoint, velocity);
}
}
float wave;
boolean anchorStop = true;
Vector anchorPoint = new Vector();
Vector waveMovement = new Vector();
//adds a wave motion to the object
void sinMove(float xWave, float yWave, float speed)
{
//find the anchor of the Object before wave movement starts
if (anchorStop)
{
anchorPoint = position;
anchorStop = false;
}
//create vector with wave motion
waveMovement = new Vector(sin(wave) * xWave, cos(wave) * yWave);
//apply motion
position = useVector.addVelocity(anchorPoint, waveMovement);
wave += speed;
}
ArrayList <Vector> attackVectors;
float fireRate;
float coolDown;
void attackSetup(Vector direction, float rate)
{
attackVectors.add(direction);
fireRate = rate;
}
Vector bulletSpawn;
void attackCycle()
{
//check for out of bounds
if (attackVectors.size()>0)
{
//if cycle is reset
if (coolDown <= 0)
{
//use all attacks
for (int a = 0; a < attackVectors.size(); a++)
{
bulletSpawn = useVector.addVelocity(position, attackVectors.get(a));
EBulletStack.add(new Bullet(position, attackVectors.get(a)));
}
coolDown = fireRate;
}
//cycle interval
if (coolDown>0)
{
coolDown -= 1/frameRate;
}
}
}
}
//VECTORS
//physics class
class Vector
{
//x and y values
float x;
float y;
//empty new Vector(0,0)
Vector()
{
x = 0;
y = 0;
}
//new Vector(x,y)
Vector(float a, float b)
{
x = a;
y = b;
}
//function for adding movement using a velocity Vector
Vector addVelocity(Vector position, Vector velocity)
{
return new Vector(position.x + velocity.x, position.y + velocity.y);
}
}
Wednesday, October 3, 2018
Processing - Procedural Motion
Code:
MAIN:
//useClass functions
//Vector class stores and manipulates floats x and y for horizontal and vertical
Vector useVector = new Vector();
//Player
//player size x and y
Vector playerSize = new Vector(20, 20);
//Vectors
//player position x and y
Vector playerPos = new Vector();
//player speed and direction as x and y
Vector playerVelocity = new Vector();
//input direction of the player x and y
Vector inputVector = new Vector();
//Input
//movement keys
char[] moveKeys = {'d', 'a', ' ', 's'};
//input axis for the movement
int[] moveValues = new int[4];
//Movement
//horizontal velocity
float moveSpeed = 5;
//Jump
//input for jumping
boolean jumpPress;
//locks the input so it only applies once per press
boolean singleJump;
//magnitude of jump velocity
float jumpForce = 7.5;
//is on the floor
boolean floorTouch;
//amount of platform to be drawn
int platformCount = 15;
//position of each platform
Vector[] platformStart;
//size of eachplatform
Vector[] platformEnd;
void setup()
{
size(500, 700);
//center the player
playerPos = new Vector(width/2, 0);
//build the platforms
platformSetup();
}
void draw()
{
background(240, 200, 200);
//get player input
moveInput();
//get jump input
jump();
//apply physics
playerPhysics();
//draw platforms
platform();
//platform collisions
collide();
//draw player
drawPlayer();
saveFrame("output/gp_####.png");
}
void drawPlayer()
{
fill(200, 200, 200);
rect(playerPos.x, playerPos.y, playerSize.x, playerSize.y);
}
void moveInput()
{
//set a directional vector based on the keyboard input directions pressed
inputVector = new Vector(moveValues[0] - moveValues[1], moveValues[2] - moveValues[3]);
}
void keyPressed()
{
//add input value on key input
for (int a = 0; a < moveKeys.length; a ++)
if (key == moveKeys[a])
{
moveValues[a] = 1;
}
}
void keyReleased()
{
//remove input value on key input
for (int a = 0; a < moveKeys.length; a ++)
if (key == moveKeys[a])
{
moveValues[a] = 0;
}
}
//gravity, drag, and movement
void playerPhysics()
{
//gravity
playerVelocity = useVector.gravity(playerVelocity);
//drag
playerVelocity = useVector.drag(playerVelocity);
//movement
playerVelocity.x = inputVector.x * moveSpeed;
//add velocity
playerPos = new Vector(playerPos.x + playerVelocity.x, playerPos.y+playerVelocity.y);
}
//jumping mechanics
void jump()
{
//Jump Input when vertical input vector is positive
if (inputVector.y > 0)
{
jumpPress = true;
}
else
//turn off jump input and
{
jumpPress = false;
singleJump = true;
}
//Add jump velocity
//check if touching floor
if (floorTouch)
{
//jump input
if (jumpPress && singleJump)
{
//add velocity
playerVelocity.y = -jumpForce;
//fire once boolean
singleJump = false;
}
}
//accelerate faster if player releases jump input
if (!jumpPress && playerVelocity.y < 0)
{
playerVelocity.y += 0.2;
}
//
if (playerVelocity.y > 0)//!jumpPress && playerVelocity.y > 0)
{
playerVelocity.y += 0.1;
}
}
void collide()
{
//reset floor trigger;
floorTouch = false;
for (int a = 0; a < platformCount; a ++)
{
//only run if there is a platform
if (platformStart[a] != null)
{
//check if the player is contacting floor collider;
if (playerPos.y + playerSize.y >= platformStart[a].y)
{
//check if the player is on the platform from the left
if (playerPos.x + playerSize.x >= platformStart[a].x)
{
//check if the player is on the collider from the right
if (playerPos.x <= platformStart[a].x + platformEnd[a].x)
{
//check if the player is above the collider
if (playerPos.y <= platformStart[a].y + platformEnd[a].y)
{
//enable jumping
floorTouch = true;
//stop downward velocity
if(playerVelocity.y > 0)
{
playerVelocity.y = 0;
}
//keep the player above the platform
playerPos.y = platformStart[a].y - (playerSize.y);
}
}
}
}
}
}
}
//create platforms
void platformSetup()
{
//platform positions and dimensions
platformStart = new Vector[platformCount];
platformEnd = new Vector[platformCount];
//first platform for the ground
platformStart[0] = new Vector(0, height - 100);
platformEnd[0] = new Vector(width, height);
//make a bunch of random positions for platforms
for (int a = 1; a < platformCount; a ++)
{
//random positions
platformStart[a] = new Vector(random(0, width), random(0, height -100));
//platforms with some random width
platformEnd[a] = new Vector(random(50, 100), 10);
}
}
//draw the platforms
void platform()
{
fill(100, 100, 200);
//draw each platform
for (int a = 0; a < platformCount; a ++)
{
rect(platformStart[a].x, platformStart[a].y, platformEnd[a].x, platformEnd[a].y);
}
}
VECTOR CLASS
//Vector class stores x and y positions but can also be used for manipulating velocity using the same Vector type;
//aka it handles basic 2D physics
class Vector
{
//horizontal and vertical;
float x;
float y;
//forces
float gravity = 9.11/60;
float drag = 0.01;
//if empty statement make new Vectors(0,0)
Vector()
{
x=0;
y=0;
}
//declare a new vector with new values;
Vector(float a, float b)
{
x = a;
y = b;
}
//returns a velocity with gravity acceleration
Vector gravity(Vector velocity)
{
return new Vector(velocity.x, velocity.y + gravity);
}
//returns a velocity with drag deceleration
Vector drag(Vector velocity)
{
return new Vector(velocity.x - velocity.x * drag, velocity.y - velocity.y * drag);
}
}
Wednesday, September 26, 2018
Processing Image [animated]
//So some advice I got when learning Unity this summer was to simply name variables something that evokes their
//purpose but I apologize in advance if my freudian brain definitions make no sense in english.
//Rectangles
//amount of rectangles to be drawn
int rectCount = 100;
//arrays for setting the position of the rectangles
float[] rectPosX;
float[] rectPosY;
//rate that the rectangles will tremble
float rectWander = .2;
//colours for the background
int[] bColour = new int[3];
//colour range
int negativeLimit = 240;
int positiveLimit = 255;
//Arc shape
//arc rotation
float arcMotion;
//Vein graphics
//ammount of veins to be drawn
int veinCount = 30;
//arrays for the positions of the circle trails
float[] veinPosX;
float[] veinPosY;
void setup()
{
size(1000, 800);
background(200);
//initiates the starting positions of the squares and circle trails
squareSetup();
veinSetup();
}
void draw()
{
//draw the background
drawBackground();
//draw veins
drawVeins();
//draw Rectangles
drawSquares();
//draw center arc
polarShape();
}
//Setup functions
//set the positions of all the squares inside the array
void squareSetup()
{
//set the size of the arrays for the rectangle positions
rectPosX = new float[rectCount];
rectPosY = new float[rectCount];
//set each value in the array to a random position
for (int a = 0; a< rectCount; a++)
{
rectPosX[a] = random(0, width);
rectPosY[a] = random(0, height);
}
}
void veinSetup()
{
//set the position arrays to set amount
veinPosX = new float[veinCount];
veinPosY = new float[veinCount];
//set random X positions
for (int a = 0; a < veinCount; a++)
{
//set x positions randomly along screen width
veinPosX[a] = random(0, width);
//set y positions randomly below screen with some offset
veinPosY[a] = random(height, height + height/2);
}
}
//DrawFunctions
//change the background colour
void drawBackground()
{
//change the value for each colour
for (int a = 0; a < bColour.length; a ++)
{
//make the colour values change at random
bColour[a] += int(random(-3, 3));
//add or subtract the colour values if they fall out of
//set range
if (bColour[a] < negativeLimit)
{
bColour[a] = negativeLimit;
}
if (bColour[a] > positiveLimit)
{
bColour[a] = positiveLimit;
}
}
//manually limit a colour's range outside of automated loop
bColour[1] -= 10;
//draw the background
fill(bColour[0], bColour[1], bColour[2], 7);
rect(0, 0, width, height);
}
//draw the squares
void drawSquares()
{
noStroke();
fill(150, 150, 150);
//draw all of the rectangles with their set locations
for (int a = 0; a < rectCount; a ++)
{
//draw rectangles
rect(rectPosX[a], rectPosY[a], 50, 80);
//make the rectangles tremble
rectPosX[a] += random(-rectWander, rectWander);
rectPosY[a] += random(-rectWander, rectWander);
}
}
void polarShape()
{
//rotating arc shape
fill(255, 220, 175);
arc(width/2, height/2, 300, 300, radians(arcMotion*2), radians(arcMotion*2 + 90));
//bottom pulse circle
fill(180, 120, 300);
ellipse(width/2, height/2, 250 * cos(arcMotion*.01), 250* cos(arcMotion*.01));
//top pulse circle
fill(100, 100, 300);
ellipse(width/2, height/2, 250 * sin(arcMotion*.01), 250*sin(arcMotion*.01));
//rotate the arc shape
arcMotion +=2;
}
//draw trailing circles that move upwards
void drawVeins()
{
//Im not sure why im commenting these functions still it's pretty hard to forget them at this point
fill(200, 100, 150);
//draw all the circles
for (int a = 0; a < veinCount; a ++)
{
//draw the circles
ellipse(veinPosX[a], veinPosY[a], 10, 10);
//make the circle trail wander
veinPosX[a] += random(-3, 3);
//make the circles move upwards towards the origin;
veinPosY[a] -=3;
//if the trails rise above the screen reset them randomly
if(veinPosY[a] < 0)
{
veinPosY[a] = random(height, height + height/2);
}
}
}
Subscribe to:
Posts (Atom)