Tuesday, February 26, 2008

Turn-based Physics Strategy

This game has many things I want: turn-based strategy, ball physics, and arrows that follow the damn cursor:
Ballistic War.

Tuesday, February 19, 2008

Arg. Stupid Lines. And TREE FIGHT!

I'm having slightly better luck with the dragging and dropping approach, but only slightly. I also figured out how to limit the maximum length of a line (function that returns MaxX or MinX, or MaxY or MinY, if they are outside of the established bounds- which would be something like point.x-50 for the MinX, for example. It'll be a square, but it'll be an invisible one, so who cares?).
I just can't figure out how to make the points and lines display correctly. But I have a plan:

While (win condition is not met):
1. Build an array filled with tree arrays (one for each player) that will contain all of the branch objects.
2. Have a "build new branch" function/mode. While it is on (user doesn't push "finish" button; still has resources):
2a. "Point selection mode" - while it is true, points are not created, only "selected" (but not really; I'm cheating a little). When one of the points is clicked on (they will have event listeners conditional to the different modes), the graphic drawing MoveTo point is set to that point's coords.
At this point, the array index of the "selected" point is recorded in public variables.
Turn off selection mode.
2b. "Newpoint mode" - while it is on, adds a listener for a mouseclick. When mouse is clicked, 2bA. build a new point (branch object) at this click and add it to the array. This includes the point(x&y,color,size), the previous point's index (recorded in step 2a), a line going from the selected point to the new point, and a size value. The size value is determined by the previous branch's size (minus one?). The new point's x and y will have built-in maximums and minimums surrounding the selected point, checked for in a small function (2bB).
2c. check for collision- if a new branch has hit another, the smaller has broken! It needs to be deleted from the array, along with every branch it was connected to. HOW DO I DO THIS? Perhaps the new branches should be added as children of the Selected branch they grew from!(!)
Otherwise (if that doesn't work), try adding "Next Branch" index along with "Prev Branch" index to each branch's properties.
Another idea: branches that are not connected to the ground should fall, and then you can't build off of them anymore. How to handle runners, then?
3. Clear every graphic in the 2d array, then redraw every branch object: point(size,color,x&y); line from previous' x&y to this one; both at the stored size value.
Return to 2a until user pushes "finish" or runs out of resources.
4. When user is done with build new branch mode, next user gets to go. Return to 2a with new user.
5. After all users have had a turn:
5a. Gather sunlight and soil data. Soil data can just be the number of points that a user has underground (below a certain Y value), but sunlight will be tricky (need to figure out a collision detection system, so that only the top branch in line with the sunlight drop will get it)
5b. Increment size values for every branch based on sunlight and soil data. Basically, soil number will act as a maximum for a user's sunlight number - or should it be the other way around? Either way, the number that isn't the maximum for the other will be the user's resource pool, able to be either spent on new branches or growth of old branches (or roots, which will work the same way, but be counted for soil instead of sunlight). So if soil acts as a maximum for sunlight, the user can have as many segments up in the air as he wants, but won't be able to collect any more resources than the lower number. I can just make that a conditional- if sun <> soil, take soil.
Size values will be incremented thusly: starting from oldest branch (not the seed; it should grow for free along with the first branch), proceeding through the tree array to newest, each size is incremented by "one" (the value that is incremented should be a const static variable up-top).
Resource pools should be kept through turns instead of emptied- leftover points will be spent next turn (or whenever). Branches can only increment once per turn (the array doesn't run through until all resources are used).

Now, I'm not certain about win conditions- I'm thinking either the First Branch (probably the first root segment growing from the seed) needs to be destroyed, or the player has to reach across the other player to the opposite end of the field. Maybe either one wins you a victory!

Blocking out the sun/cutting off the roots of your opponent are key to victory.

More ideas for how to accomplish this:
Disease (inflicted on a branch, has a random chance to get well, every turn it is sick, a branch loses an increment of size)
Squirrels (random or maybe rare special power, builds a seed in an area away from your tree)
Runners (roots can spring up from the ground into trees elsewhere- should this be a normal thing that every tree can do? What happens when a runner is separated from the seed?)
I think an ultrarare "cannon fruit" that you can fire at your enemy tree (treemesis?) would be pretty slick.

(NOTE: using increments defined at the top, rather than hard numbers, is useful because then different trees can be implemented; one might have different growing speed, one might have different "branch size" limits when placing new branches, one might be more susceptible to disease, one might be more likely to attract squirrels/seed carriers)

Drawing Trees.

I've been working on getting the tree-drawing code down. I've devised ways of drawing points, adding them into a big ol' tree array (which is, again, in another array). Each player will have their own tree array made of objects-points and lines, mostly. I've figured out how to change player colors on turn-switch, and done the coding for the actual display of points (making certain to add the objects I make to the array first, and then recall those objects to add them to the stage, thus preventing another week-long hassle with me not knowing if my arrays are working correctly or not).
The display of the branches is giving me a little bit of a hassle, mostly because I'm not certain how to make certain objects be "selected." I want the player to have to select a point, and then place a new point (and line) from that point, eventually adding the stipulation that the point must be a certain distance away from the original point (not sure how to do this, either- can I somehow chop off the end of the line, if it's too far away? I think a better method might be to drag-and-drop from the point you want to make the new branch off of, and just implement an "invisible wall" kind of thing around that point).

In fact, I'm going to go try that.

[forum post]

Tuesday, February 12, 2008

Conversations with Mostly Myself

Never tell your password to anyone.
publictom: what
rollinkunz: what
publictom: you need equations!
rollinkunz: yeah i know!
rollinkunz: i totally do
rollinkunz: i need hellz of equations
rollinkunz: i want to make my trees sway in the breeze
rollinkunz: and stuff
rollinkunz: not sure how i'll do that
rollinkunz: not even sure how i'll make the trees in the first place
publictom: y = y + .01; x = sin ( y )
publictom: and when y goes off the screen reset it to zero
rollinkunz: what is this for?
publictom: trees swaying!?
publictom: oh
publictom: um
publictom: yeah you could do that with trig too
publictom: ill think about it
rollinkunz: i need to first figure out how i'm going to make the trees.
rollinkunz: i think what i'll do,
rollinkunz: okay,
rollinkunz: so i found ways of having the user click to draw points, and then having lines appear in the points
rollinkunz: so that's good
rollinkunz: the points are then still able to be moved
rollinkunz: which is good too; i just don't want the user to move them
rollinkunz: which i'm sure is easy to change
rollinkunz: but then i also need to do things like make the lines scalable
rollinkunz: because the tree segments need to grow
rollinkunz: and i need to figure out how to concatonate the lines to the correct length as they are placed- so maybe the draw-dots thing isn't the best
rollinkunz: unless i had it be a two click system, where the point that the user wants to draw off of is first selected, and then the cursor is somehow limited to staying within a radius within that point?
rollinkunz: that would probably work
rollinkunz: just need to figure out how to do it
rollinkunz: and then i just put all the points in a big array, and run it through a few growing functions
rollinkunz: which will be easier
rollinkunz: also i need to figure out a slick function for determining which points are in sunlight, which are in shade, and which are underground
publictom is now Away.
rollinkunz: the thing about using drawn lines for the branches is: 1. they won't be as pretty, and 2. i don't know how to adjust their scale easily, and remember that scale
rollinkunz: i guess i could do it with a separate, parallel array or something? hmm
rollinkunz: maybe i can store the drawn segments in objects somehow?

Sunday, February 10, 2008

Elasticity/Bounce Effect

Tutorial to add bounce or elasticity to objects (spiffy).

Ding! Effect Achieved

Here's the field of cursor-reactant holes:
http://www.uwm.edu/~rakunz/files/DrawAndGrow.swf

...And here is a field of cursor-reactant kitties:
http://www.uwm.edu/~rakunz/files/DrawAndGrowKitties.swf

Note: forum people are super useful.

This is Important (Dynamic Drawing)

Thought I'd make a note of FlashAndMath.com's tutorials, specifically this one (which I shall be needing to draw trees with!). Adding it to the links, as well.

Cursor-Reactant Holes!

It works! Just needs some formula-tweaking, and my little baby will be complete.

Another thing I have learned:

If you have some commands that you want to put in a class, you can't just put them in the class definition. You have to put them in a function. I was trying to declare a Timer in my class definition, which is fine, because it has to be a public variable. Not fine is trying to use the addEventListener() and start() functions of the Timer class outside of any sort of function. So the solution was (inside the MovingHoles class, in a file named MovingHoles.as):

public var Time:Timer = new Timer(10);

//contructor function
public function MovingHoles(){

//makes a timer and declares a function that is called by it
Time.addEventListener(TimerEvent.TIMER, rescaleHoles);
Time.start();
}

I found my solution here.

As Seen On: the Forum!

Well, that's another problem taken care of.

Apparently, I was making each value in allHoles() into a new array, then pushing a different array into the next value and deleting the last one (over and over)... I didn't even think that my array was being built wrong, because I had the same function doing the building of the array and the drawing of the objects in it (which had the unfortunate side effect of drawing each object right before it was overwritten by a new array). So I had a field of holes drawn on my screen (making me believe my array was being built successfully), but they were mere empty husks of their former data-object selves.

The way I was accessing the objects from the 2D array was never the problem at all- so agonizing over the syntax for hours trying to figure out why I couldn't access the objects that were clearly on my screen just makes me feel so damn silly.

Anyway, my code still doesn't compile, but I think this next error might be just a syntax error (instead of a gaping hole in my logic that both destroys my program and fools me into thinking the wrong part of it is the problem). We're going to learn about Timers!

Side note: Programming forums are really, really useful. Why do people spend their time offering free, professional-quality advice to people that obviously have no idea what they're doing? It boggles the mind, until you realize that everyone starts out having no idea what they're doing, and that this is exactly how the Internet is meant to function: the dissemination of information, culture, technology, and ideas through free-access, ubiquitous channels. I am a part of the world.

Thursday, February 7, 2008

New Problem! and Blur Tutorial.

I can't figure out how to access the properties of clips stored in objects stored in multidimensional arrays. In a nutshell. I'll let you know how to do it once I do!

But hey: here's an example of how to use a built-in filter to blur stuff! Could be useful...

Undefined Term Problem Solved

Okay, I have fixed the undefined term problem- found I needed to use "allHoles.push(holes)" and "holes.push(thisHole)" instead of "allHoles[x].push(holes)" and "holes[y].push(thisHole)" - stupid syntax error.

I think Actionscript 2.0 would've let me do that.

Problem and Updated Pigs

Okay, so I'm trying to make a new prototype to test out and play with multidimensional arrays (as well as arrays of Data Objects, which can have clips as components).

Here's what I have so far (well, there are a bunch of variable definitions and such as well, but here's the main array-makin' function):

//makes a field of holes
function drawHoles() {
var allHoles:Array = new Array(); //creates horizontal array to store vert. arrays
for (var x:uint=0; x < boardWidth; x++) {
var holes:Array = new Array(); //creates new nested vertical array of data objects
for (var y:uint=0; y < boardHeight; y++) {
var thisHole:Object = new Object();
thisHole.holerow = x; //this property is which row the new object is in
thisHole.holecolumn = y; //this property is which column the new obj. is in
thisHole.holeobject = new hole(); //adds a hole graphic to the object
thisHole.holeobject.x = x*holeHorizontalSpacing; //assigns x of graphic
thisHole.holeobject.y = y*holeVerticalSpacing; //assigns y of graphic
holes[y].push(thisHole); //adds new hole to a vertical array
addChild(thisHole.holeobject); //adds graphic to stage
}
allHoles[x] = new Array();
allHoles[x].push(holes);
}
}

The thing won't run- I think I'm doing something wrong, but I'm not certain what. All the Flash debugger will tell me is that I have an "undefined term with no properties." Hmmm.

On the plus side, I cleaned up that previous project a little more and added a few things: The flying pig now randomly resets its height and scale when it respawns, slowly rocks back and forth (in the wind), and is draggable!

Code for that stuff:

Swaying pig (inside the timer event function):

//this set of ifs keeps track of which way the pig should sway, and sways it.
if (clickOffset == null) {
if (swayDir) {
pig1.rotation += .2;
swayCount += 1;
} else {
pig1.rotation -= .2;
swayCount -= 1;
}
if (swayCount > 30) {
swayDir = false;
}
if (swayCount < -30) {
swayDir = true;
}

if (upPig) pig1.y -= scrollSpeeds.pigzoom*.1;
else pig1.y += scrollSpeeds.pigzoom*.1;
}
prevX = mouseX;
prevY = mouseY;
}

Random pig respawn (also in the timer event function):

if (pig1.x >= (ground1.width/3*2)) { //randomize and reset pig!
randy = Math.random()*(Math.random()*5)+.1;
pig1.scaleX = randy;
pig1.scaleY = randy;
pig1.y = (Math.random()*400);
pig1.x = -(ground1.width/3*2);
scrollSpeeds.pigzoom = randy;
if (pig1.y > 300) upPig = true;
else upPig = false;
}

Make the pig draggable (this is where that "clickOffset == null" condition for the swaying code came in- if the pig is being dragged around, it won't keep swaying back and forth):

//add dragging and dropping functionality to pigs:
pig1.addEventListener(MouseEvent.MOUSE_DOWN,startclipDrag);
stage.addEventListener(MouseEvent.MOUSE_UP,stopclipDrag);
pig1.addEventListener(Event.ENTER_FRAME,clipDrag);
//offset between sprite location and click:
var clickOffset:Point = null;

function startclipDrag(event:MouseEvent) {
clickOffset = new Point(event.localX, event.localY);
}

function stopclipDrag(event:MouseEvent) {
clickOffset = null;
}

function clipDrag(event:Event) {
if (clickOffset != null) {
pig1.x = mouseX - clickOffset.x;
pig1.y = mouseY - clickOffset.y;
}
}

The "clickOffset" records where you clicked the pig, then the clipDrag function keeps the difference in positions the same when you drag the pig around.

Anyway, I'm going to post this question up over at the actionscript.org forums and see if I get an answer.

Wednesday, February 6, 2008

Parallax Example

Here is a my sweet prototype parallax scrolling background.
Might not be sizing up right (it's not in a webpage or anything) but you get the idea so far.

http://www.uwm.edu/~rakunz/files/Parallax.swf

Parallax Backgrounds / Scrolling in ActionScript 3.0

So what we have here is a timer (which calls a function), a Data Object which holds a bunch of values for different scrolling speeds, a bunch of different Movie Clips (added in the order they should be drawn), and a big ass function that both automatically scrolls some of the layers (clouds and a pig) and scrolls every layer based on mouse movements.

I couldn't find any ActionScript 3.0 code for this, so I ended up coding it from scratch. I decided to compare the mouse X and Y positions at each tick with the positions of the previous tick, and then use that value as a constant to multiply by the various scrolling speeds (so that different layers are offset and the illusion of depth is created). I am so God Damned clever.

Oh yeah, and there's some code at the bottom that respawns the cloud layers and pig once they venture too far along the X axis. This is so the clouds and pigs may scroll forever, as opposed to just once.

Why didn't I just make one function to scroll around via mouse? I should've. Such a function would take the mouseX and mouseY, the previous values for each, the Movie Clip, and the clip's scroll speed and return new X and Y coordinates for the clip. One short function instead of one behemoth function. Hm. Next time.


Code: (things in bold are new commands)


var Time:Timer = new Timer(10);
Time.addEventListener(TimerEvent.TIMER, scrollLayers);

//these hold the previous timer tick's mouse position values
var prevX:int = mouseX;
var prevY:int = mouseY;

var scrollSpeeds:Object = new Object(); //holds different scroll speeds
scrollSpeeds.backclouds = 1;
scrollSpeeds.frontclouds = 2;
scrollSpeeds.pig = .25;
scrollSpeeds.sky = .2;
scrollSpeeds.cloudMouseX = .2; //how fast to scroll clouds in reaction to mouse
scrollSpeeds.cloudMouseY = .4;
scrollSpeeds.groundX = 1;
scrollSpeeds.groundY = .2;

var backsky1:backsky = new backsky();
backsky1.x = 275;
backsky1.y = 300;
addChild(backsky1);

var pig1:flyingpig = new flyingpig(); //makes a pig!
pig1.x = -200;
pig1.y = 50;
addChild(pig1);

var backclouds1:backclouds = new backclouds();
backclouds1.y = 150;
backclouds1.x = 0;
addChild(backclouds1);

var backclouds2:backclouds = new backclouds();
backclouds2.y = 150;
backclouds2.x = backclouds2.width;
addChild(backclouds2);

var frontclouds1:frontclouds = new frontclouds();
frontclouds1.y = -50;
frontclouds1.x = 0;
addChild(frontclouds1);

var frontclouds2:frontclouds = new frontclouds();
frontclouds2.y = -50;
frontclouds2.x = frontclouds2.width;
addChild(frontclouds2);

var bgrass1:BGrass = new BGrass(); //background grass
bgrass1.x = 275;
bgrass1.y = 420;
addChild(bgrass1);

var ground1:ground = new ground(); //foreground
ground1.y = 500;
ground1.x = 300;
addChild(ground1);

var grassroots1:grassroots = new grassroots(); //foreground roots
grassroots1.x = 275;
grassroots1.y = 490;
addChild(grassroots1);

var agrass1:AGrass = new AGrass(); //foreground grass
agrass1.x = 275;
agrass1.y = 410;
addChild(agrass1);



function scrollLayers(event:TimerEvent) {

//scrolls layers according to mouse movement
backsky1.x += (mouseX - prevX)*scrollSpeeds.sky;
backsky1.y += (mouseY - prevY)*scrollSpeeds.sky;
backclouds1.x -= (mouseX - prevX)*scrollSpeeds.backclouds*scrollSpeeds.cloudMouseX;
backclouds1.y -= (mouseY - prevY)*scrollSpeeds.backclouds*scrollSpeeds.cloudMouseY;
backclouds2.x -= (mouseX - prevX)*scrollSpeeds.backclouds*scrollSpeeds.cloudMouseX;
backclouds2.y -= (mouseY - prevY)*scrollSpeeds.backclouds*scrollSpeeds.cloudMouseY;
frontclouds1.x -= (mouseX - prevX)*scrollSpeeds.frontclouds*scrollSpeeds.cloudMouseX;
frontclouds1.y -= (mouseY - prevY)*scrollSpeeds.frontclouds*scrollSpeeds.cloudMouseY;
frontclouds2.x -= (mouseX - prevX)*scrollSpeeds.frontclouds*scrollSpeeds.cloudMouseX;
frontclouds2.y -= (mouseY - prevY)*scrollSpeeds.frontclouds*scrollSpeeds.cloudMouseY;
ground1.x -= (mouseX - prevX)*scrollSpeeds.groundX;
ground1.y -= (mouseY - prevY)*scrollSpeeds.groundY;
grassroots1.x -= (mouseX - prevX)*scrollSpeeds.groundX;
grassroots1.y -= (mouseY - prevY)*scrollSpeeds.groundY;
agrass1.x -= (mouseX - prevX)*scrollSpeeds.groundX;
agrass1.y -= (mouseY - prevY)*scrollSpeeds.groundY;
bgrass1.x -= (mouseX - prevX)*scrollSpeeds.groundX*.5;
bgrass1.y -= (mouseY - prevY)*scrollSpeeds.groundY;
pig1.x -= (mouseX - prevX)*scrollSpeeds.pig;
pig1.y -= (mouseY - prevY)*scrollSpeeds.pig;

//scrolls clouds constantly (each tick)
backclouds1.x -= scrollSpeeds.backclouds;
backclouds2.x -= scrollSpeeds.backclouds;
frontclouds1.x -= scrollSpeeds.frontclouds;
frontclouds2.x -= scrollSpeeds.frontclouds;
pig1.x += .5;

//regenerates clouds once they scroll too far
if (backclouds1.x <= -backclouds1.width) backclouds1.x = backclouds1.width;
if (backclouds2.x <= -backclouds2.width) backclouds2.x = backclouds2.width;
if (frontclouds1.x <= -frontclouds1.width) frontclouds1.x = frontclouds1.width;
if (frontclouds2.x <= -frontclouds2.width) frontclouds2.x = frontclouds2.width;
if (pig1.x >= ground1.width) pig1.x = -200;

prevX = mouseX;
prevY = mouseY;
}

Time.start();

Oops Blogging is Hard

Okay, so I really should have been updating this as I went this past week.

But I didn't.

It's alright.

What I've accomplished:

1. I have a solid idea for my finished product: Tree Fight! It's all plotted out and such; I have multiple design pages devoted to it. I will transcribe them when I am not so sleepy. Be excited.

2. Along those same lines, I got my friend Keith on-board for Tree Consultation (he is a lumberjack). Cleared up quite a few things about how trees actually grow and function and die, many of which helped form and solidify my game design idea. For instance: tree roots grow mostly outward, not downward, so there is no point in having half of the playing field be underground. The roots also are not for finding aquifers or other underground water supplies, so a "water number" as a sunlight capacity resource doesn't make sense; the number of roots (basically the number of placed segments underground) will determine the sunlight capacity instead. Many more ideas where that came from.

3. My brother Chandon, who's going to school for sound design, said he'd whip up a few sounds for the end product (shouldn't take too many). This means I will have a kickin' soundtrack for my first real Flash game, to boot!

4. The big stuff (by which I mean, the piece of actual programming that I accomplished):
Parallax background scrolling! I have a little program that scrolls eight or so different layers at different speeds in reaction to the user's mouse movements! Plus, three of the layers scroll by themselves with a timer to show movement and mirth! Good Lord, I am excited. I really need to figure out a way to put Flash files up on here.