Wednesday, May 14, 2008

Make Trees, Not War

Latest version of the Treemaker.
Perhaps the last version?
It works!

Thursday, April 24, 2008

Wednesday, April 23, 2008

Trees Hate One Another

New version of Treemaker. It's automatically set in a two-player mode, to test, so realize that you are taking turns placing seeds and then branches and such for alternate trees. The player turn switches when you place a knot (not a branch with a leaf or root or an additional leaf). Sunlight gathering finally actually works, but resources are not properly-balanced (I'm working on it... but I'll probably get all of the basic parts working first).

Tuesday, April 8, 2008

More Things to Do:

1. Turn the branches into objects so that I may add a "IsAStem" Boolean property to each.
This property will be marked "true" if the branch ends up placing roots or leaves, and branches with "IsAStem == true" will have their growth handled differently. Turning branches into objects will also allow me to add properties like OriginalScale, which might be useful in setting the growth limits for said Stems (or perhaps these stems are simply not allowed to grow?), and ParentKnotIndex, which would allow me to delete branches and knots whose parents have been destroyed.

2. Figure out how to destroy branches, and make it so that destroying a branch kills all branches connected to the seed by it. Making the new branches AddChild onto the knot they sprang from (may need to use event.target, or even track the index of the event.target knot in a public variable) might just accomplish this.

3. Incorporate an "IsPlaceable" Boolean into the branch placement functions- it should change to "false" if the branch is overlapping an object that it cannot be placed upon (underground obstacles and enemy branches which are larger than it), and the branch placement function should recognize this and not allow branch placement there.

Treemaker Version 9

Here's the newest version of the Treemaker!
(Yes, I know it's been a while since my last post, and yes, I realize I skipped a version; version 8 incorporated things like resource calculation and the precursor to the current growth/shrinkage system.)

Instructions:
Click on the white screen to place a seed. Click on the seed to start placing branches. Branches below a certain length will spawn leaves or roots, depending upon whether they are above or below ground.
Press "a" on your keyboard to activate one round of resource calculation/growth. Pressing it quickly over and over again allows you to see lots of growth over time.

What is new:

1. Resources. Pressing "a" (make sure if you are playing with it in Flash itself, you disable keyboard shortcuts while you try it out) will activate a round of Growth. This calculates resources (including a function that, theoretically at least, tests whether each leaf is blocked by something else from the sun), meaning sunlight and roots, and then grows or shrinks each tree based upon its resource surplus/deficit.

2. Sunlight. I haven't gotten around to putting in the functions that will allow for two or more players, but they are almost there. The sunlight function draws a line from each leaf to the sun, then tests to see if anything breaks that line. It should(!) work.

3. Growth. Everything has been built and tweaked so that things should grow more or less like they are supposed to... Roots grow and shrink faster than branches/knots, and leaves do not shrink at all. The branch placement system has been changed to allow for this sort of thing without odd-looking graphical mishaps (for instance, all branches now start at the center of the knot which spawned them).
On a side note, there are now a few tree-type variables available for implementation. They're already in there as properties.

What I forgot to do:

1. Add a function that removes listeners from other knots while a branch is awaiting placement. There is still a bug remaining that will end a branch placement without a new knot, or with a leaf or something instead, if you click on a knot while you are placing a new branch.

Next time:

1. The Unlistener/Relistener functions (should be simple enough- just add a for loop that runs through each knot and removes its listener while the branch is being added, and another that adds the listeners again after its placement).

2. Multiplayer.

3. Resource limiting? Rather than not letting a player place new branches when they have negative resources (which could straight-out kill their chances of recovery), I think the shrinkage system is better- players can still come back from a bad turn, but they are penalized for poor building techniques by losing the strategic upper hand (their tree will shrink, and therefore the other player will be able to break through their branches). We'll have to see what happens through playtesting.

Tuesday, March 11, 2008

Idea for Multiplayer and Levels:

While one person takes his tree-building turn, the other player(s) expend resources on abilities to slow them down.
have a column of icons for different abilities for each player. keyboard controls their selection, activation, and control.

Example: While player 2 builds, player 1 decides to spawn a fire, which burns up random branches, destroying leaves and preventing growth for a certain number of turns.

Or: While player 3 builds, player 2 takes control of the pigs that spawn !!

Other ideas: root-eating/leaf-eating insects, squirrels that spawn seeds for sneak attacks, disease (contagious!), bomb fruits.

Ideas for levels so far: Normal field level, wherein one must capture pigs that fly by; Cave level, in which spots of sunlight are very important; Post-Apocalyptic city level, with underground and overground obstacles and bomb fruits? mines? lasers? something.

New Version of Treemaker

Treemaker version 7.

This is a huge update, though much of it is behind-the-scenes slickness.

New implementations:

1. Instead of click-and-drag, a click-and-click-again method is now used for branch placement. This helped fix a lot of the graphical errors...

2. Fixed rotation arc of roots and leaves. They now have a maximum rotation from the angle of branch placement, meaning awkward-looking leaves and roots are now less likely. Roots also sense when they are close to the surface and rotate down instead of looking at the angle of placement.

3. Extra leaves now appear from a leaf's stem when one clicks on a leaf. They have similar rotational properties as the normally-placed leaves, in fact they are identical, besides having been created by a different function. addRoot(), addLeaf(), and addKnot() are all separate functions, now. Much more streamlined. Too bad I was sloppy and ended up using two functions for the leaves- addLeaf() and addAdditionalLeaf(). But maybe the latter can be turned into addAdditionalLeaves(), and it can produce two leaves at once for the same cost as a branch+leaf. Or something. Trying to think in the context of strategy, here.

4. New branches now have a maximum scale equal to the scale of the knot they are building off of. This means no more huge branches coming off of tiny ones! This is a huge thing, and took much time. My solution involved recording the scale of the knot that is clicked on to begin the startAddBranch() method and then using it as a limiter. The syntax (and finding the event.target.scaleX command) was the difficult thing to figure out... event.target lets you access the clip (/object, perhaps?) that has been clicked on to start the current Listener method.

5. The Treemaker now keeps track of number of players and makes a newTree object that includes (so far) separate arrays for knots, branches, leafs, and Roots, the numbers of each, the branchLength for the tree (they can now be different!), and the player's resources, for each player. The newTrees are created and added to an allTrees array in a function called by the constructor function. Number of players and current player are now kept track of, as well, and all of this new organizational stuff is implemented (the program actually works with all of it, so far). This also took a long time, but it was mostly trying to translate hacked-together code into nice, neat code.


Fixed bugs (and how I fixed them):

1. Full-scale branch flashing for a moment at first click: I added a call for the rotate() method before the addChild for the branch (so the branch is rotated and scaled before it's placed). The rotate() method (along with pretty much everything else) received and overhaul.

2. Extra leaves appearing when trying to click-and-drag a new branch from an overcrowded knot: Making the branch building click-and-click-again fixed this; I actually decided to implement it correctly after it had been removed as a bug (#3).

3. Ground-level bug- sometimes leaves would appear below ground level, or roots above: This was fixed (more or less) by moving the seed slightly below ground level and having roots and leaves sense where they've been placed in relation to the ground level (instead of trying to use the coordinates of the point they've been built off of). Trace commands of groundLevel and the corresponding leaf/root variables were helpful.

4. Ends of new branches slowly cover up knots: I played around with this, ended up moving the registration for the branches up one point on the x axis, but decided that there needed to be some sort of limiter for the number of branches coming off of a single knot.

5. Roots scaling too small: I made them scale up according to a certain formula, instead. They start at half scale and go up from there. Looks pretty decent.


Bugs that Remain:

1. Once in a while, a new branch is placed slightly off of its knot, or a new knot is placed slightly off of its branch. No big deal; I also have no idea why it happens. Might not be happening in latest version.


Treemaker Parts Left to Implement:

1. Try adding new branches onto the ones they grow from with addChild(). Hopefully, this will make removing everything after a break in a branch as simple as removing the segment that broke.

2. Need a method to remove branch segments, for fighting and perhaps for own-tree-tweaking.

3. Add resources, including a method of calculating them (take lower number of sunlight & soil), a way of calculating sunlight and soil (need to figure out hit detection for the sunlight, probably), and something that keeps track of the resources as they are used (and prevents the player from using more than they have).

4. Add growth, after resources are sorted out. Each branch and knot's scale should be incremented by a certain amount for a certain resource cost, once the player's turn is over and remaining resources are calculated.

5. Add wind effect (leaves move in tandem according to some sort of timer-based formula function)- have to send each player's array of leaves through a function that changes their rotation.

Metagame Parts Left to Implement:

1. Title screen, with buttons that allow the user(s) to change the settings- pick number of players and each player's tree type, as well as level select. Need to make art for title screen, buttons, and different trees. Plus the graphics for every level.

2. Figure out the whole "level background" thing. This means turning the parallax scrolling level I made into a nice, neat com package that can be imported by my document class. And designing and drawing new levels. Eventually. This includes adding wind, sun, etc.

3. The actual turn structure! This is big, but probably not that difficult to figure out. Players each have a turn, starting from player one and rotating through until the number of players has been reached. Each player's first turn consists of placing their seed. Subsequent turns allow the player to spend resources on branches (MAKE SURE THERE'S A COUNTER TO KEEP TRACK OF RESOURCES OF EACH PLAYER) or bank them to make their tree's scales larger. Fighting comes into play. When every player's turn is over, the SUN comes by and grants a refill on resources (up to each player's resource cap, determined by number of leaves and roots). This means there needs to be a way to determine how much sunlight each tree gets (sunlight needs to be blockable by branches/knots). This is while the win conditions are not met, of course-- CAPTURE THE FLAG, wherein every tree tries to rack up points by controlling (being the only one with branches in) a certain area, seems like a good idea.

RESOURCE NOTES: Additional leaves should cost less than original ones (maybe?), smaller branches should cost less (maybe?)

4. Results screen, after the game has ended (player reaches goal (or number of capture points) or destroys first branch of all other players). Have some player stats (number of branches, leafs, and roots broken, number built, number of players killed, time in capture area, resources collected, etc.

IDEA: Maybe make this a capture-the-flag sort of game? Or have options for different playing modes- capture the area, deathmatch, grab the pig, or twixt (get across the opponent to the other side).

5. Additional game elements: squirrels/new seed placements, rain?, disease, fire?

Saturday, March 8, 2008

Flash Game of Note: Caravaneer

Caravaneer: Post-apocalyptic caravan trading simulation with turn based combat. Love the complexity, the stats, the graphics, and the map movement. More here.

Tuesday, March 4, 2008

Initializing additional classes from Document Class

bam.

Bug List 1

Bugs to fix:

1. That full-size branch that automatically flashes in original position right when you click, before you start to move the mouse.
Solutions: Try putting addChild for the new branch after the rotate() call.

2. Extra leaves/roots appear when clicking on (trying to build from) an overfull knot.
Solutions: ?? Maybe some of the other fixes will fix this too?

3. Ground-level bug- sometimes roots appear above ground/leaves appear below.
Solutions: Try putting a trace on the "prev" variables, the groundLevel... be able to tell before placement whether something will be a leaf, knot, or root.
Note: might not need to worry about this (try adding the background first!).

4. The ends of new branches slowly cover their origin knots.
Solutions: Make X registration for the branches start at 0.
Note: might not be a bug, but a happy-accident (it's a useful limiter vs. overgrown knots).

5. Roots get too small-looking, but I like the varied sizes that scaling brings.
Solutions: Don't scale down for smaller roots- scale up for larger roots!

The Treemaker Cometh

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

Here's the treemaker, so far as it is. It makes a pretty decent facsimile of a tree, if I do say so myself. First click places the seed, additional click-and-drags create branches. If a branch is dragged under it's max length, the branch scales. If it's still over half of its max length, the knot that is created scales. If it's under half of its max length, it makes either a leaf or a root, depending upon whether it's above or below ground level (theoretically-that last part still has kinks in it).

I'm stoked!

My friend Tom helped me out with the scaling-of-the-branch; specifically the equations that would give the coordinates of the new knot-to-be-created. I figured out the branch rotation with the help of a neat tutorial (unfortunately in AS 2.0; had to translate it), and did the rest myself. With my mind.

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.

Wednesday, January 30, 2008

Dragon Drop

Here's a quick tutorial on dragging and dropping DOs in AS3.

That is all.

Tuesday, January 29, 2008

Chase the Dragon

Dragoneye1.addEventListener(MouseEvent.CLICK, clickEye);
Dragoneye1.addEventListener(MouseEvent.MOUSE_UP, eyeMouseUp);
var eyecount:uint = 1;
var shrinkcount:int = 9;

function eyeMouseUp(event:MouseEvent) {
Dragoneye1.rotation += (eyecount*10);
if (shrinkcount > 0) {
Dragoneye1.scaleX = (shrinkcount*10)/100 +.1;
Dragoneye1.scaleY = (shrinkcount*10)/100 +.1;
Dragonhead1.rotation -= .1;
shrinkcount -= 1;
} else if (shrinkcount == 0) {
Dragoneye1.scaleX = .1;
Dragoneye1.scaleY = .1;
Dragonhead1.rotation -= .1;
shrinkcount -= 1;
} else if ((shrinkcount > -11)&&(shrinkcount < 0)) {
Dragoneye1.scaleX = (shrinkcount * -10)/100 +.1;
Dragoneye1.scaleY = (shrinkcount * -10)/100 +.1;
Dragonhead1.rotation += .1;
shrinkcount -= 1;
} else {
shrinkcount = 10;
}
}

function clickEye(event:MouseEvent) {
if ((eyecount == 1)||(eyecount == 2)) {
trace("Poke.");
} else if (eyecount == 3) {
trace("Pooooooke.");
} else {
trace("Poke!");
eyecount = 0;
}
eyecount += 1;
}


This is a little script that plays with rotating and scaling DOs using a couple of different user interactions (really the same one- a mouse click- but CLICK is different from MOUSE_UP in theory). So, yes: using graphics, moving graphics, using mouse clicks: check.

I love the .rotation property that's built into... well, every display object, at least. Simple, fast, and easily-modified! Logic is fun.

Next up: buttons.

Spawning Graphical Elements(!)

var Dragonhead1:Dragonhead = new Dragonhead();
Dragonhead1.x = 280;
Dragonhead1.y = 200;
Dragonhead1.rotation = 0;
addChild(Dragonhead1);

var Dragoneye1:Dragoneye = new Dragoneye();
Dragoneye1.x = 402;
Dragoneye1.y = 160;
Dragoneye1.rotation = 0;
addChild(Dragoneye1);

for (var i=1;i<20;i++) {
var eye:Dragoneye = new Dragoneye();
eye.x = 50*i+50;
eye.y = 50*i+50;
eye.scaleX = (i/5);
eye.scaleY = (i/5);
addChild(eye);
}

Lots of new stuff here:
Now that I've made a couple of "movie clips" (really just sprites at this point) to work with, I can start a little bit on the non-absolute-basic stuff.

"var Dragonhead1:Dragonhead = new Dragonhead();" creates a new instance of one of my graphics. The next two lines tell it where to appear on the stage, and the last places it. (So, to set or change the placement of an object, use the .x and .y properties of the object.) Rotation is another handy property, as is .scaleX/Y - they allow me to change the size of the graphic on-the-fly (yay for vector graphics!).

I probably should have spent less time on the graphics, but at least they look pretty.

Iffy

If and else statements work like in C++. So do && and || (and and or, respectively).
for, while, and do while work the same, as well. Functions, too. Good to know.

Time to start learning to use visual elements!

Special Ops

++ increments positively,
-- increments negatively,
+=, -+, *=, and /= all perform their respective operations on the original variable.

Example: "VARIABLE /= 88;" divides VARIABLE by 88.

String variables can be added to with the + and += operators (to make bigger strings).
That'll be useful once this book finally starts talking about user input(!).

Variables 1

You can call a variable using something like "var VARIABLE = 13", and it can then be used to store whatever the hell you want. Sloppy. Assigning types to the variable, like "var VARIABLE:int = 13", constrains the content of the variable. Using smaller types (int, Boolean, uint) is more efficient than using larger types (Number, etc.).

Types:

int = integers
uint = positive integers
Number = floating point numbers (fractions)
String = text
Boolean = bools (true/false values)

You can also put in arrays, sprites, movie clips, and custom types.

Quick Notes on Display Objects

Display objects are graphic elements.

They may contain other display objects (for example, one "sprite" can contain all of the sprites you want, plus other kinds of display elements). Nesting DOs like this is useful because they are then easily-organized.

ActionScript 3 lets us use a display list with nested DOs, which allows us to move around their display order (on the Z plane, that is; not X, Y, or In Time). DOs can be moved from one parent DO's display list to another's.

Also, and this is somewhat unrelated, but very important, frames and keyframes are not used extensively in Flash game programming, nor in the same way, as in animation. They are used to organize the different elements and screens of the game, and determine which elements of the game (such as score) carry through to different screens. IMPORTANT.

Classes in Session

How to make classes in Flash (in an external ActionScript file):


package {
import flash.display.*;
import flash.text.*;

public class HelloWorld extends MovieClip {

public function HelloWorld() {
var rollinText:TextField = new TextField();
rollinText.text = "Hello, World. I am a part of you.";
addChild(rollinText);
}
}
}

Okay, so this is a lot of knowledge here. Previous OOP experience required (maybe).
This is an external ActionScript file, not a movie. package tells Flash that the file is a package containing a class. The next two lines call other built-in classes (flash.display and flash.text) so that we may call upon their powers to assist us.

Then there's the new class definition. public tells Flash that the class is public (obviously) and can be called on from wherever in the code you want. "extends MovieClip" lets the class work with a movie clip (the Flash stage).

Then, inside the class, there is a single function, named the same as the class. This is important because it makes the function the class's constructor function - the function will run as soon as the class is initialized. Hmm. The function is the Hello World function from before, which just creates a TextField, puts some text in it, and displays the text on the stage.

Okay, sweet. So now I know how to make an external class in Flash and call it in a Flash movie clip. The actual clip was completely empty- it just had a link to the class, basically, and the class just had a constructor function, so it was like bam bam bam. Now I need to learn... a whole bunch more stuff! Onward!

Hello World

First program was a Hello World.

Commands learned:

trace("anytext"); - Outputs a line of text, where anytext = whatever you want to output. Note that this does not actually display text in a Flash movie- just in the output box. For debugging.

Here's the code for a Hello World in Flash:

var rollinText:TextField = new TextField();
rollinText.text = "Hello World. I am a part of you!";
addChild(rollinText);

What this does, in order, is call a new variable (var) named rollinText as a TextField (which is an object that displays text on the Flash stage). Not sure yet why there are two parts to the declaration process (the :TextField part and the = new TextField() part).
Next, it assigns the text property of the TextField. (That's what the ".text =" means. The stuff in quotes after it is the text I want to display onscreen.)
Finally, it adds the TextField object to the stage with the addChild command.

When I tested it, the stage didn't display my whole text- I had to scroll it. Tried to play around with some functions I didn't know about to fix it, then decided to put it off 'til later.

Ready Go

I've received ActionScript 3.0 Game Programming University in the mail, so I'm going to start plowing through it and posting notes here.

Thursday, January 24, 2008

Flash Games of Note

Got to start somewhere. I think it's important to acknowledge what others have done before me, and learn from them- figure out the capabilities of the medium, that sort of thing.
In this spirit, I've done a bit of "research" into current Flash games (the first batch of many, I'm certain).

Notable:

Makibishi Comic - It's got a wonderful graphic style, and fleshed-out sound. I'd like to learn how to create those parallax backgrounds.

Four Second Frenzy - Well this is just fun. What better example of game design than a Wario-Ware type Flash collection? The variety of different control methods, all using the same few keys (arrows and space bar) is something to think about.

Areas and Filler both use simple shapes (and their resizing) to great effect. Filler is basically an interesting take on Jezzball, while Areas is an Asteroids clone that manages, somehow, to convey creeping doom through a weird soundtrack and a series of mysteriously-expanding circles.

Dupligon is a puzzle from the standpoint of a newbie trying to recreate it. In it, the player is given a shape, then told to draw it (with vertices) from memory. The size and orientation of the new shape don't matter, when comparing it to the old, just the angles... So I'm guessing it 1. finds the coordinates of the vertices, 2. calculates the lines between them, 3. finds the inclusive angles (trig!), and 4. compares them to the original shape's angles. Hmm.

Travian is an example of a massively-multiplayer Flash strategy game (which I one day aspire to create). Players build up their little villages and pillage/trade with other players. Unfortunately, it plays out in "real time" and is therefore kind of boring to get going in. That is something to think about- if a strategy game is both massively-multiplayer and turn-based, does each player have to wait for all of the others before making their next move? (Obviously, that would be really annoying, if not impossible... what to do?)

General Idea (for a massively-multiplayer strategy game): Players can choose to "lay out" their next few moves. The timer runs, and the database takes turns for the players in their absence. This would mean that players wouldn't have to be at their computers, waiting for the timer for their next turn to count down... but doing so might give players a (well-earned) strategic advantage.

Right-o: Mission Statement!

Hello. My name is Rollin. I want to learn Flash this semester- not just animation and such, but Actionscripting 3.0 and all the fun that comes with.
This blog will be an account of my journey.
You will find here my notes, works-in-progress, a journal of my trials and tribulations, and links to intriguing examples of and references for Flash I find along the way.

My first mission: create a static button that starts an animation, which then loops back to the stasis from whence it came. My tools: the Internet, as the two references I've ordered (ActionScript 3.0 Game Programming University and Flash CS3 Professional for Windows and Macintosh (Visual QuickStart Guide)) have not yet arrived, as well as Flash CS3 (of course).

Stay tuned.