******

Post your own tutorials, guides and demos.

Post » Wed Jun 18, 2008 4:35 pm

LOL .. i hit the windows shortcut for page back in IE explorer at almost the end of my next post. LOL .. all gone .. LOL .. *hits head* I need to start writing this outside IE. But all my other spell checkers are DUTCH talking !!!! LOL.

Oh btw this IE plug in containing this spell checker is just plain awesome.
Google for IEpro.
I actual love this plug in.

Well, i got to start over. First will be dinner.
B
3
S
2
G
4
Posts: 322
Reputation: 2,119

Post » Wed Jun 18, 2008 7:04 pm

Here i go again.

Add 4 Private variables to the object vault.

X_to, number, 0
Y_to, number, 0

X_from, number, 0
Y_from, number, 0

go to the events editor.

First we have to store the Position of the Head in variables before it moves to a new place.

This has nothing to do with the X_head and Y_head variables we made earlier.
They are not holding a position. The head will never be positioned at 0,-10.

X_head and Y_head are holding "relative values"
Relative values have not much meaning by there own. They relate to something. They only get a meaning by adding them to a absolute value. Like we added them to the Head's position to move the Head 10 pixels.

The Values we use to remember Heads old position are absolute value's.

We gonna store Heads X and Y in the variables X_to and Y_to. Because thats what the first body will jump to.

So locate the comment "move head"

there is the condition "every 100 milliseconds" and its sub condition always.

Easier then adding a new sub tree to all this...
is again go by the *lazy editing* way.

Duplicate the always sub-event.

Now you have a duplicate of the event and its actions. And on the right branch in the tree.

We need to store the variables before the Head moves.
So, delete the actions behind the first "always" sub event.

And we are ready to code.

hit new action behind the first "always" sub event.

Step1: self object = Vault
Step2: action = set value
step3: parameters: private variable = X_to / value = Head.X

finish

Yes, Head.x not .x The self where "." refers to is Vault in this action not Head

Duplicate that action.
Double click it.
step3: Private variable = Y_to / value = Head.Y

finish

There, now we we always know where the Head was before it moved.

Now lets snap the first body to that position.

Locate the comment "move body"

Double click the "always" event under it.
Automatically you land in step2 of the events wizard. Thats because "always" has no parameters. Another, you probably think coincidental, reason to make a structure with comments and "always"'s before starting to code. I will try always to start a tree of events with a flow condition.

step2: condition : For Each Object (ordered)
step3: parameters : select Body as object (its a pick condition) / Order expression = Body.UID /
Mode = Ascending

Finish

Body.UID and not .UID because its a condition, conditions dont know "selfs", only actions do.

what is the property UID ? it stands for Unique ID. Every object, made in the layout editor or/and made by events, will get an Unique ID, a number. The first made object will have a lower UID then the second made object. Not necessarily 1 and 2. But for sure ascending.

For Each Object (ordered) is a pick condition.
It well run trough the instances of the object chosen in the parameters step. One by one. And feed this instance as picked (one by one) to its sub-events and actions.
It will do that in an order and direction you told it to do.

In this case, it will pick the instances of the object Body. One by one, and feed them one by one to the sub-events and actions we gonna make for it.

It acts as a Loop. And it will adjust its end to the count of instances for Body in this layout. In other words, we can add as many instances of the object body on runtime as it pleases us, the "For Each" will just adjust and take into account all instances.

Now well the condition is in place. Now it needs actions.

First we will store the position of the currently picked instance of Body in a variable. Before we move it.

Lets *lazy edit* . Under the events moving the head u see the action
Vault Set 'X_to' to Head 0 .X

Duplicate it by CTRL + dragging it to the actions of the "For each" we are working on
Double click the copy.

step3: parameters: private variable = X_from / value is Body.x (self = Vault)
finish

Duplicate that action.
Double click it

step3: parameters: private variable = Y_from / value = Body.y

finish

There thats that.
Now we stored its position, we can move the currently picked Body instance.

click new action.

step1: self = Vault
step2: action = set x
step3: parameters: it will be an expression.
double click Vault in the expressions guide
double click the expression "get private variable"
Body.Value('Variable name') will be filled in (you can of course type all that too)
change it to Vault.Value('X_to')

finish

Duplicate the action.
double click
click one step back to step2

step2: action = set Y (select, and click next)
step3: ahh that expression is still here, just change X_to in Y_to

finish ...

Now all we have to do is change point of view from the current picked instance of Body, to the point of view for the next instance the pick-condition will pick.

For the next instance, the X_from will be the X_to. So all we have to do is store the value of X_from into X_to (same for Y)

X_from is where the previous instance jumped from, and the point the next instance will jump to.


Lets *lazy edit* this.

Duplicate the "Vault Set 'X_to" and the Vault Set 'Y_to' actions from the "move head" events to the place of actions that we are working at.

Double click the "Body: set 'X_to" action (2 actions back under this event)
Copy the expression in it ( Vault.Value('X_to') )
click cancel or finish

double click the first duplicated action. the one that sets the X_to
step3: just paste the clipboard content in the value. And change X_to in X_from

finish

A computer is made to copy and paste, and for nothing else !!!

double click the second duplicated action.
step3: just paste the clipboard content in the value. and change X_to into Y_from

finish

note: every time i make an expression, i will trow it in my clipboard. Usually turns out to be handy.


Run all to check. And it looks like a big mess. And theoretical. The math is right.

Most beginners stop here. At this point. (or at the next problem).

And yet, there error is easy.

We forgot the "every 100 milliseconds" condition. In other words .. Head and body run out of sync.

Aha !!!

OK lets sync them up. Add a another ""every 100 milliseconds" condition" ?
Nah,
lets not do that.
Just drag the event tree with the "For each" loop up, under the second always that moves the head, and on the same tree level.

Delete the "move body" comment.
Edit the "move head" comment to "move head and body"

there, run all again.

Perfect!!!! Only a snake can not move backwards, lol. oh thats easy solved.
And we will in next post.

Here is how the events should look, if you ran in a problem, compare with is picture.
Maybe it was my english, or you forgot a detail somewhere. So check up with this.



I do not want to post the .cap. Because i really need you to type and click all this.
Else it is no tutorial. sorry ?
B
3
S
2
G
4
Posts: 322
Reputation: 2,119

Post » Wed Jun 18, 2008 8:06 pm

Actual, its funny to see that snake walk backwards.

But, it has to go.

Lets first analyze "backwards" ..
The snake can not change direction to the right when we are all ready going left. = backwards.
Not left when currently going right.
Not up when currently going down.
Not down when currently going up.


When is the snake going right ? How do we know ?
Well, when X_head = 10

We go left when X_head = -10

We go up when Y_head = -10

and down when Y_head = 10

When do we change direction ?
Well when the corresponding key is pressed.

So we just have to link the keys with a condition to X/Y_head variables.

Lets add conditions based on this to the key inputs.

STOP ! you yell. You said no conditions to key inputs.

I meant, no conditions to key inputs on top of them. They will slow them down. And the event sheet looks like a mess.

Key board and mouse detection conditions are triggers. Currently in construct they dont act as triggers yet.

A trigger will pause the execution of events, run the action and sub events under a trigger condition, and when done with them, return in the events sheet where it paused.

I am sure this will be implemented some day in construct. Therefor, today already i threat triggers as triggers.

Rule 1: triggers will always be the first event in a tree.

So lets add conditions to the keyboard triggers to LIMIT execution of its actions.
NOT on top of the key conditions to limit the key inputs.
You are allowed to place hundredths of sub_events under the key conditions, just not 1 on top.

Select the condition "on key Right".
Right click choose "insert new conditon"

step1: object = vault
step2: condition = "Compare a private variable"
step3: private variable = X_head / comparison is "not equal to" / value = 10

finish

Now lets *lazy edit*

Ctrl + drag that condition into every "on key" condition.

then double click copy by copy to edit the conditions.

Key left
private variable = X_head / comparison is "not equal to" / value = -10

key up
private variable = Y_head / comparison is "not equal to" / value = 10

key down
private variable = Y_head / comparison is "not equal to" / value = -10

Run all

Yup, this is right. eh ?



In next post we bring in the pray for this hungry little snake.
B
3
S
2
G
4
Posts: 322
Reputation: 2,119

Post » Wed Jun 18, 2008 9:14 pm

go to the layout editor.

Add a sprite from the butterfly animation that in the folder with sprites i provided for this tutorial.
Any of the butterfly sprites will do.

Yes this gonna be an animation, but a simple basic one.

Name it "Butt", yes i like little joke in my events.
Bite my butt, hahahaha, oopz.

Set width and hight to 20. It is a bit to big now, compared to the snake.
Not that its gonna look realistic. But though ........

Place it outside the layout canvas. We will bring it on screen by an event.

Now we add animation.

With Butt selected, click the "animator" TAB on the organizer on the right.

The Animator has two screen parts. On top you see the animations.
Below the middle you see the sprites (frames) that make up the animation.

On top you see "default" and a sub entry "angle:0"


"Default" is the name we will call the animation with in the events.

In the animator "Default" acts as a folder, containing animations that match with the angle of the object.

When we want to animate a walking man. We want him to have his nose to the right when he's walking to the right. This animation is different (mirrored) when he walks to the left, nose faced to the left.

When u add an animation for 0(faced right) and 180 (faced left), construct will automatically use the right animation when the angle of the object changes to left or rigtht.

NOTE: You can mirror sprites by giving it a negative width (or hight) in its properties. Bet not to many people know this.

But our animation will not change direction. It will not walk. The butterfly will just sit and wait patiently to be eaten by the snake.

Told you, we will only use basic things in this game.

So select the sub entry "angle: 0 attached to "default". (Yes you can change "default' to another name in the left properties pane, if it annoys you.)

So select the sub entry "angle: 0 attached to "default".
This is what actual is containing the animation frames.

On the bottom part you will see one sprite, numbered 1. At the moment there is 1 frame in the animation. Right click it. Choose "import frames" from the contextual menu.

The file explorer comes up. Point it to the folder containing all the butterfly's that i provided.

Press CTRL+a to select them all. Or have your way clicking and selecting them all.

Click open.

Now you are confronted with a import wizard.
I can not explain u everything in this wizard. I dont know it in depth yet. But there are not to many buttons and check boxes to figure it out, if you want to.

For now, just click "import"

The frames will be imported.
And you can see them, and bring them in the picture editor by double clicking a frame.
This why i say "one frame of an animation is also a sprite"

The sprite is no more then a variable property of an object. This sprite will animate its face over time. And thats close to animate X over time. Same thing.

Now with angle:0 still selected, change its speed in the properties on the left to 12.

note:
Initial its set on 50.
To give you an idea about commonly used animation speeds :
35 mm Cinema (the big movies) runs at 24 images / sec (a speed of 24)
television in Europe runs at 25 full images / second
in America thats 30 images / second
Most .gif animations on the Internet are set to a speed of 12 images /second (most monitors are set to 60 hertz, and 60/12 gives a whole number)


ok thats enough for now. Lets bring the butterfly with an event in the layout, and lets get it eaten by the snake.
B
3
S
2
G
4
Posts: 322
Reputation: 2,119

Post » Wed Jun 18, 2008 10:15 pm

Butt will jump to a random place on screen when the snake eats it.

But that condition does not exist on start of the game. You will find yourself many times in that situation.

Now you can do this. Create a global flow variable like Is_but_eaten. And give it the value "yes" when starting up the game.
And make the Butt event move the Butt when that global variable is set to "yes"
The variable gets set to "yes" when the snake eats the Butt. And will be set "no" right after the Butt is moved to another place.

In general, sometimes you have to force conditions to happen at startup of the game, to get the flow nicely going.

In this game we will keep things simple. But be aware of all this.

We will not use a flow for moving the Butt.

And we will use the "On layout start" condition to bring in the Butt for the first time.

Every action, and sub events attached to "on start layout" will run between the moment that you run the game and the moment its screen pops up.
Or when we restart the layout, in the moment between the screen changes.

It will only run once, and be excluded from the top-down execution during the rest of the game.

Right click the "start of layout" condition (C-spot), and add a sub condition "always" to it.

click new action to this "always"

step1: self = Butt
step2: action = set X
step3: parameter: will be an expression ..
double click system object in the expression guide
scroll some trough the expressions .. as you see this is heaven for the math freak
locate "generate random number"
double click it
it will bring random(1.0) in the X field

now change this to ((random(61) ) * 10 ) + 15

we need the Butt also to be on the 10x10 grid
not to close to the left edge of screen and in the middle of the grid ..

screen width = 640 - 15 for the left border - 15 for the right border = 610

610 / 10 (grid is 10 based) = 61

so random(61) will generate a number between 0 and 61
* 10 will give 10 based numbers

+15 will place it in the middle of the grid, and not to short to the left side.

click finish.

Duplicate that action.
Click back 1 step.

step2: action = set Y
step3: parameters : change the expression to ((random(46) ) * 10 ) + 15

click finish
B
3
S
2
G
4
Posts: 322
Reputation: 2,119

Post » Wed Jun 18, 2008 10:21 pm

...
B
3
S
2
G
4
Posts: 322
Reputation: 2,119

Post » Thu Jun 19, 2008 4:29 pm

If you run this as it is, the snake will move under the Butt object.

I would rather have the Snake moving in front of the Butterfly.

Go to the layout editor.

Bring up the layer organizer on the left.
Add a new layer on top, with the little green up arrow key.
Drag the newly created layer One down, so it is in the middle of the 3 layers.

Locate the Butt object in the object list in the layer organizer plane. Depending on the filter in the middle you might have to select another layer to see it.

Then drag it from that list up into the middle layer (on upper half of the organizer)

Now we have in the lowest Z-order layer, the bottom layer, the grid.
On top of everything we have the Snakes head and its body.
In between them we have the butterfly.

The other objects are not visible, they dont really matter. But to be a good boy, u could organize them on a special layer, that you name "controls", or so.

If the snakes body's instances are not on the most top layer, then also drag this object to the top layer.

As you see, its easy to organize Z-orders in construct with layers.
B
3
S
2
G
4
Posts: 322
Reputation: 2,119

Post » Thu Jun 19, 2008 5:23 pm

Back to the Events editor.

When the snake hits the Butt object. Butt will jump to a new random location.
Currently, nothing happens if we move the snake over Butt.

How does the snake know where the Butterfly is ?

We can of course compare the Head's position to the Butt's position in an compare event. If they are at the same place, we can consider the Butt as eaten.

Thats very basic. But lets not do it this way.

There are also the system pick condition "object overlaps point" and "object collides with point"
Its a pretty fast condition.

We could use an expression to feed the X and Y of the Butt to the X and Y in the parameters of an "object overlaps point" system condition, and as object the Head.

This pick condition will pick all instances of an object, and only the instances that overlaps the point given by the X and Y coordinates, will be feed to the sub events and actions.

But lets not do it this way.

Locate the comment "eat".
Add a sub event to the "Always" condition thats already in place there.


Step 1: base object = butterfly (we will move the butterfly)
Step2: condition= Is overlapping another object
step3: parameters: object is Head

finish

This is a pick condition. Its takes all instances of the object Butt, and when an instance will overlap with an instance of the object Head, both that instance of Butt and the instance of Head will be set as picked and be feed to the sub events and actions.

When there is no object picked, i think, no actions and no sub event will run.

Now just copy the 2 actions that randomly placed the object Butt in the "start of layout" event to here.

Run this, play a little with it.

And it will be like the Butterfly jumps away to early.
Yes from the moment both overlap even with 1 pixels, then the conditions are met.
Also the butterfly is a little bigger then the 10 based grid, so when ...
the Head is not going besides it, they will overlap too.

Go to the layout editor. Select the Butterfly. Locate "collision" in its properties. And change it to point.

Run all again.

Now the collision detection is only made when there middle points (the pivot points) overlap each other.

And yes this is better.

Under the collision options you will find 4 options.

None = this object will not detect collision, AND will NOT be DETECTED BY OTHER objects.
Point = Only the pivot point is used for detection.
Bounding box = Only the bounding box is used to detect collisions.
(when you select an object in the layout editor, the bounding come visible as a box of lines)
Pixel = All pixels in the sprite are used as sensors to detect collision.

Point will check only one point. which is the fastest detection.
Bounding will only check the points defined by the math for a rectangle. Its a little slower then "point".
Pixel will check every point of the sprite, when the sprite is very complicated, thats a slow kind of detection.

Two objects that detect each other can have different detection methods. And the result is a combination of both.

When one is on "bounding" and the other on "point". The detection well be made when the pivot point of that one overlaps the bounding box of that other.
B
3
S
2
G
4
Posts: 322
Reputation: 2,119

Post » Thu Jun 19, 2008 6:12 pm

At same time as the butterfly gets eaten, we add another body part.

It dont really matter at where we create this new instance. Because, the "For Each" pick condition will find it and bring it to the right place.

Just to avoid a flicker, we will create it out of screen.

Since this happens under the same conditions that makes the Butt jump to a new location,
we just add it as action on that place.

add a new action the "Butt overlaps Head" event.

step1: choose system object
step2: action = create object
step3: parameters: object = body / layer = 2 / X = -20 / y = -20

finish

Run all and play some with it.

change the "eat" comment to "eat and grow"
delete the "grow body" comment and its "always" pre-made event
B
3
S
2
G
4
Posts: 322
Reputation: 2,119

Post » Thu Jun 19, 2008 6:38 pm

Dude, Dudette ...

Thats pretty much that we have done with ONLY 12 events. With Only 6 variables so far.
Dont you think ?

If you look at or original planning, there are only 2 more things to do.
The dead situations, and the "let the player start over again" situations.


The player will die if the Head will go out of screen, and if the Head bites own body.

If its Dead, we will pop up a little message.
And we will not move the head.
We will not limit the key inputs, just keep the Head from moving.

In other words, when its dead .. the other events need to know.

Its time to bring a little flow in the game.

Make global variable by ..
Click project in the top menu,
Click "manage variable" on the ribbon.

The variable wizard pops up, and its the same as this one for "private variables"

Make a variable as follow

name = Player_Is
type = text
value = dead and alive

That value dont really matter.
Why ?
well .. When you use a Global variable ..
and the variable's value is essential for the game starting out the right way ...
THEN YOU HAVE to initiate the variable in the events.

And best place to do this is in the "start of layout" event.

Add a new action under the actions randomly moving Butt in the "start layout" event.

step1: object = system object (its holding the global variables)
step2: action = Set value
step3: global variable = Player_Is / value = "alive" (including the "'s )

finish


select the "ever milliseconds" condition (C-spot).
Right click and "insert new condition"

step 1: object = system object
step2: condition = compare global variable
step3: parameters: global variable = Player_Is / value = "alive"

finish

There will be no overlapping to detect, if the Head is not moving.
So this event does not need this FLOW condition.

Ok lets Kill the snake.
B
3
S
2
G
4
Posts: 322
Reputation: 2,119

PreviousNext

Return to Your tutorials & example files

Who is online

Users browsing this forum: No registered users and 0 guests