I'm looking for a solution for a loop with a array of images - processing.js

so what i'm trying to do is to change the images that's stored in a array that contains 16 imgs, it's basically a animation for when you play a game (press forward character moves[moving imgs], release button character stops[stoped img]). The thing is that after the array reaches it's length max and the key is still being pressed it needs to reset the array to 15 (so this loop will give the illusion of the constant movement), but i think i'm not finding the right synthax or something.
Thanks in advance.
PImage p1;
PImage[] zeroArray = new PImage [16];
void setup() {
size(600,600);
for(int i = 0; i < zeroArray.length; i++){
zeroArray[i] = loadImage (i + ".png");
}
}
void draw() {
background(255);
imageMode(CENTER);
if(keyPressed) {
i++;
} else if (i > zeroArray.length) {
zeroArray[] = zeroArray[15]; // <--this ain't right, how should i declare this??
}
image(zeroArray[i], 300, 300, 800, 800);
}

I think you're mixing a few ideas into one if statement. Let's take a look at this section of your code:
if(keyPressed){
i++;
}
else if (i > zeroArray.length){
zeroArray[] = zeroArray[15];
}
Run through this line-by-line and really think about what it's doing. If a key is pressed, it increments the i variable. If a key is not pressed, then it checks whether i is greater than the length of the zeroArray array variable. If it is, it attempts to reset the array, which is not valid syntax.
Take a step back and think about what you're trying to do. Forget about code for a second. Write down exactly what you're trying to do, in English. My guess is you're trying to do something like this:
Change the image being drawn whenever the key is pressed.
If we reach the end of the images, then start over at the first image.
When you have something like that written out, that's an algorithm that you can start thinking about implementing with code. Break your problem down into smaller steps and take those steps on one at a time.
For example, step 1 is to change the image whenver the key is pressed. You basically have that already:
if(keyPressed){
i++;
}
Then, step 1 is to reset the i variable whenever it reaches the end of the array. You might do that using an if statement like this:
if(i >= zeroArray.length){
i = 0;
}
Putting it all together, it would look like this:
if(keyPressed){
i++;
if(i >= zeroArray.length){
i = 0;
}
}
Now this code checks if a key is being pressed, and if so it increments the i variable. It then checks whether the i variable has gone past the end of the array, and if so it reset it back to the beginning.
If that's not exactly what you're looking for, then the process of solving your problem is still the same: you need to write down, in English, exactly what you're trying to do. You need to do that before you start hammering away at the code.

Are you sure you want to reset the array to 15? That's the last element. However, in general, the solution would be to change the line:
zeroArray[] = zeroArray[15];} // <--this ain't right, how should i declare this??
to
i = 15; //Just change the index pointer to 15 (or whichever frame you want to reset to)

Thank you all for the answers, they really gave me some light.
To Kevin Workman.
Writing down the path that i intended to take really helped out, your thinking was almost on point. Using your method i came up with this
1)Change character sprites if key is being pressed
2) Reset movement to a certain point in case it exceeded the animation sprites, and the key is still being pressed
3)Set to fist sprite if the key is released or not being pressed at all
To Sahil Jain
You were right about changing the index to [15], it didn't work so well
Here is the revised code:
PImage p1;
PImage[] zeroArray = new PImage [16];
void setup(){
size(600,600);
for(int i = 0; i < zeroArray.length; i++){
zeroArray[i] = loadImage (i + ".png");
}
}
void draw(){
background(255);
imageMode(CENTER);
if (keyCode == RIGHT){
if(keyPressed){
i++;
} else {
i = 0;
}
if (i >= zeroArray.length){
i = 4;}
image(zeroArray[i], 300, 300, 800, 800);
}
}

Have you tried switching your else if to your main argument in the last If...Then statement? Also, don't forget to reset your variable i to 0 so it resets too and doesn't continue to always try to reset and end up in an infinite loop of sorts :)
As it is in your code in the question, it does the increment first and will never follow through to read into the second choice (the one you want it to do).

Related

XNA 2D object collision (without Tiles/Grid)

First time posting here. Tried to look for topics previously to help.
I'm using Visual Basic, but so far I've been able to follow C# and just translate into VB.
I would like collision without tiles. Smooth movement without any sort of snapping. I already have the movement down, and my sprites stop at the edges of the screen.
I've read I could use Bounds and Intersects, which I have tried. When I apply an IF statement to the arrow keys each time they are pressed, using Bounds and Intersects (I just prevent sprite movement if it is intersecting), it works for ONE key. I move left into an object, and I stop. If I apply the IF to all keys, it will work the first time. Say I move left into an object, the IF statement checks if the Intersects is true or not and acts accordingly.
Now I want to move right, away from the object. I can't since my sprite is ALREADY colliding with the object, since each arrow key is programmed to NOT move if there is Intersection. I see perfectly why this happens.
The code I currently have: (Each arrow key has the same code, altered to it)
If Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Right) And rBlockBounds.X <=
graphics.GraphicsDevice.Viewport.Width - rBlockBounds.Width = True Then
If rBlockBoundBoxBounds.Intersects(rObstructBounds) Then
rBlockBounds.X += 0
rBlockBoundBoxBounds.X = rBlockBounds.X - 1
Else
rBlockBounds.X += 1
rBlockBoundBoxBounds.X = rBlockBounds.X - 1
End If
End If
rBlockBounds is my sprite As Rectangle
rBlockBoundBoxBounds is another Rectangle (1 pixle bigger than rBlockBounds) used as a Hit Box more or less that moves with rBlockBounds, and is the thing doing the collision checking
rObstructBounds is the stationary object that I'm moving my Sprite into.
Anyone have suggestions on how I can make this work?
Since I myself program in C#, not VB I can not code your solution but instead I can explain a better way of approaching it.
What you want to do is prevent the two rectangles from ever intersecting. To do this you will need to implement a move method into your code which can check if the two tiles are colliding. Here is a C# example:
public bool MoveX(float distance) // Move Player Horizontally in this example
{
rBlockBounds.X += distance;
if(rBlockBoundBoxBounds.Intersects(rObstructBounds)
{
rBlockBounds.X -= distance;
return false;
}
return true;
}
Which essentially means that if you run into an object you will be pushed out of it. Since it occurs in one tick you won't get any jutty back-and-front animations.
And that should do what you want. You can test this out and then implement it for y-coordinates as well.
Also, you might notice I've made the function return a bool. This is optional but allows you to check if your player has moved or not.
Note if you teleport an object into another one it will cause problems so remember to implement this every time you move anything.
But that should do what you want.
Edit
Note since your objects are not in a tiled grid, you will need to move lots of time in very small steps.
Something like this:
public bool MoveX(float distance) // Move Player Horizontally in this example
{
rBlockBounds.X += distance;
if(rBlockBoundBoxBounds.Intersects(rObstructBounds)
{
rBlockBounds.X -= distance;
return false;
}
return true;
}
public bool MoveX(float distance, int repeat)
{
for(int i=0; i < repeat; i++)
{
rBlockBounds.X += distance;
if(rBlockBoundBoxBounds.Intersects(rObstructBounds)
{
rBlockBounds.X -= distance;
return false;
}
}
return true;
}
Where the second one will take multiple steps. Here is why you would use it:
MoveX(500); // Will move 500 right. Could easily skip over objects!
MoveX(5, 100); // Will move 5 right one hundred times
// ^ This will take more time but will not skip object
Similarly for yours you could do this:
MoveX(3); // If contact object will be max 3 pixels away
MoveX(1, 3); // If contact object will be max 1 pixels away
MoveX(0.5f, 6); // If contact object will be max 0.5 pixels away
Now I am guessing all your x, y positions are integers. If so you could get away doing the second call and come exactly next to each other. If not you would do the third call.
Hope this helped.

Share data between scripts?

I want to create a scoring system. I have 4 buttons with 4 different but similar scripts and want to share 1 GUI Text for the scores. Example Code:
var something : Sprite;
var SpriteRenderer : SpriteRenderer;
var score : int = 0;
var guiScore : GUIText;
function OnMouseDown () {
if(SpriteRenderer.sprite == something) {
score += 1;
guiScore.text = "Score: " = score;
}
}
Right now, if I pressed a button and got a point then I pressed a different button the score would start from 0 again. How can I share data something like static variables but different scripts? I know this sounds a bit noobie but any help would be much appreciated. Thanks in advance
Static variables won't appear in the inspector so you can't assign the GUIText in the inspector (thanks for making me find out). So try using GetComponent instead:
// make a variable of type GUIText
var guiScore: GUIText;
// assign the gameobject in the inspector
var staticObject: GameObject;
// Again I don't know the name of your script, so I'll name it StaticScript
// get the script
StaticScript scr = staticObject.GetComponent(StaticScript);
// assign local GUIText with the one from above
guiScore = scr.guiScore;
This way you have already shared 1 GUIText for all other scripts.
However you said:
Right now, if I pressed a button and got a point then I pressed a
different button the score would start from 0 again
Doesn't that mean something is wrong with the score, not the GUIText?

Add boundaries to an SKScene

I'm trying to write a basic game using Apple's Sprite Kit framework. So far, I have a ship flying around the screen, using SKPhysicsBody. I want to keep the ship from flying off the screen, so I edited my update method to make the ship's velocity zero. This works most of the time, but every now and then, the ship will fly off the screen.
Here's my update method.
// const int X_MIN = 60;
// const int X_MAX = 853;
// const int Y_MAX = 660;
// const int Y_MIN = 60;
// const float SHIP_SPEED = 50.0;
- (void)update:(CFTimeInterval)currentTime {
if (self.keysPressed & DOWN_ARROW_PRESSED) {
if (self.ship.position.y > Y_MIN) {
[self.ship.physicsBody applyForce:CGVectorMake(0, -SHIP_SPEED)];
} else {
self.ship.physicsBody.velocity = CGVectorMake(self.ship.physicsBody.velocity.dx, 0);
}
}
if (self.keysPressed & UP_ARROW_PRESSED) {
if (self.ship.position.y < Y_MAX) {
[self.ship.physicsBody applyForce:CGVectorMake(0, SHIP_SPEED)];
} else {
self.ship.physicsBody.velocity = CGVectorMake(self.ship.physicsBody.velocity.dx, 0);
}
}
if (self.keysPressed & RIGHT_ARROW_PRESSED) {
if (self.ship.position.x < X_MAX) {
[self.ship.physicsBody applyForce:CGVectorMake(SHIP_SPEED, 0)];
} else {
self.ship.physicsBody.velocity = CGVectorMake(0, self.ship.physicsBody.velocity.dy);
}
}
if (self.keysPressed & LEFT_ARROW_PRESSED) {
if (self.ship.position.x > X_MIN) {
[self.ship.physicsBody applyForce:CGVectorMake(-SHIP_SPEED, 0)];
} else {
self.ship.physicsBody.velocity = CGVectorMake(0, self.ship.physicsBody.velocity.dy);
}
}
}
At first, I used applyImpulse in didBeginContact to push the ship back. This made the ship bounce, but I don't want the ship to bounce. I just want it to stop at the edge.
What is the right way to make the ship stop once it reaches the edge? The code above works most of the time, but every now and then the ship shoots off screen. This is for OS X—not iOS—in case that matters.
Check out this link...
iOS7 SKScene how to make a sprite bounce off the edge of the screen?
[self setPhysicsBody:[SKPhysicsBody bodyWithEdgeLoopFromRect:self.frame]]; //Physics body of Scene
This should set up a barrier around the edge of your scene.
EDIT:
This example project from Apple might also be useful
https://developer.apple.com/library/mac/samplecode/SpriteKit_Physics_Collisions/Introduction/Intro.html
Your code is not clear in what the velocity variables represent. Keep in mind that if the velocity is too high your ship will have travelled multiple points between updates. For example, your ship's X/Y is at (500,500) at the current update. Given a high enough velocity, your ship could be at (500,700) at the very next update. If you had your boundary set at (500,650) your ship would already be past it.
I suggest you do a max check on velocity BEFORE applying it to your ship. This should avoid the problem I outlined above.
As for bouncy, bouncy... did you try setting your ship's self.physicsBody.restitution = 0; ? The restitution is the bounciness of the physics body. If you use your own screen boundaries, then I would recommend setting those to restitution = 0 as well.
Your best bet would be to add a rectangle physics body around the screen (boundary). Set the collision and contact categories of the boundary and player to interact with each other. In the didBeginContact method you can check if the bodies have touched and, if they have, you can call a method to redirect the ship.
Your problem is that your update method may not be checking the location frequently enough before the ship gets off screen.
This will help you to define you screen edges in Swift.
self.physicsBody = SKPhysicsBody ( edgeLoopFromRect: self.frame )

Problems in my AS2 Game

Hey guys, I'm trying to make a 2D Platform style game similar to this game below:
http://www.gameshed.com/Puzzle-Games/Blockdude/play.html
I have finished making most of the graphic, and areas, and collision, but our character is still not able to carry things. I'm confused as to what code to use so that my character can carry the blocks. I need help as to how to make our character carry blocks that are in front of him, provided that the blocks that don't have anything on top of it. This has been confusing me for a week now, and any help would be highly appreciated. :D
I fondly remember my first AS2 game. The best approach is probably an object oriented approach, as I will explain.
In AS2, there is a hittest method automatically built into objects. There is a good tutorial on Kirupa here:
http://www.kirupa.com/developer/actionscript/hittest.htm
also
http://help.adobe.com/en_US/AS2LCR/Flash_10.0/help.html?content=00001314.html
First you'll want to generate your boxes using a Box class. Your class would need to look something like the following:
//Box.as pseudo-code
class Box {
var x_pos:Number;
var y_pos:Number;
var attachedToPlayer:Boolean;
function Box(_x:Number, _y:Number) {
this.x_pos = _x;
this.y_pos = _y;
}
//other code here
}
See this tutorial on how to attach a class to an object in the library:
http://www.articlesbase.com/videos/5min/86620312
To create a new Box, you'd then use something like
box1 = new Box(100,200);
// creates a box at position 100x,200y
However, you'll also want to store the blocks you want to pickup into some sort of array so you can loop through them. See http://www.tech-recipes.com/rx/1383/flash-actionscript-create-an-array-of-objects-from-a-unique-class/
Example:
//somewhere near the top of your main method, or whereever your main game loop is running from - note Box.as would need to be in the same folder
import Box;
//...then, somewhere before your game loop
//create an array to hold the objects
var boxArray:Array = new Array();
//create loop with i as the counter
for (var i=0; i<4; i++)
{
var _x:Number = 100 + i;
var _y:Number = 100 + i;
//create Box object
var box:Box = new Box();
//assign text to the first variable.
//push the object into the array
boxArray.push(box);
}
Similarly, you would need a class for your player, and to create a new Player object at the start of your game, e.g.
var player = new Player(0,0);
You could then run a hittest method for your player against the blocks in your array for the main game loop (i.e. the loop that updates your player's position and other game properties). There are probably more efficient ways of doing this, e.g. only looping for the blocks that are currently on the screen.
Once your array has been created, use a foreach loop to run a hittest against your player in your game's main loop, e.g.
//assuming you have an array called 'boxArray' and player object called 'player'
for(var box in boxArray){
if (player.hittest(box)) {
player.attachObjectMethod(box);
}
}
This is basically pseudo-code for "for every box that we have entered into the array, check if the player is touching the box. If the box is touching, use the box as the argument for a method in the player class (which I have arbitrarily called attachObjectMethod)".
In attachObjectMethod, you could then define some sort of behavior for attaching the box to the player. For example, you could create a get and set method(s) for the x and y position of your boxes inside the box class, along with a boolean called something useful like attachedToPlayer. When attachObjectMethod was called, it would set the box's boolean, e.g. in the Player class
//include Box.as at the top of the file
import Box;
//other methods, e.g. constructor
//somewhere is the Player.as class/file
public function attachObjectMethod (box:Box) {
box.setattachedToPlayer(true);
//you could also update fields on the player, but for now this is all we need
}
Now the attachedToPlayer boolean of the box the player has collided with would be true. Back in our game loop, we would then modify our loop to update the position of the boxes:
//assuming you have an array called 'boxArray' and player object called 'player'
for(var box in boxArray){
if (player.hittest(box)) {
player.attachObjectMethod(box);
}
box.updatePosition(player.get_Xpos, player.get_Ypos);
}
In our Box class, we now need to define 'updatePosition':
//Box.as pseudo-code
class Box {
var x_pos:Number;
var y_pos:Number;
var attachedToPlayer:Boolean;
function Box(box_x:Number, box_y:Number) {
this.x_pos = box_x;
this.y_pos = box_y;
}
public function updatePosition(_x:Number, _y:Number) {
if (this.attachedToPlayer) {
this.x_pos = _x;
this.y_pos = _y;
}
}
//other code here
}
As you can see we can pass the player's position, and update the box's position if the attachedToPlayer boolean has been set. Finally, we add a move method to the box:
public function move() {
if (this.attachedToPlayer) {
this._x = x_pos;
this._y = y_pos;
}
}
Examples of updating position:
http://www.swinburne.edu.au/design/tutorials/P-flash/T-How-to-smoothly-slide-objects-around-in-Flash/ID-17/
Finally, to make it all work we need to call the move method in the game loop:
//assuming you have an array called 'boxArray' and player object called 'player'
for(var box in boxArray){
if (player.hittest(box)) {
player.attachObjectMethod(box);
}
box.updatePosition(player.get_Xpos, player.get_Ypos);
box.move();
}
You have also specified that the blocks should only move with the player if they have nothing on top of them. When you call your attachedToPlayer method, you would also need to run a foreach loop inside the method between the box and the objects that might sit on top of the box. You should now have a fair idea from the above code how to do this.
I appreciate that this is quite a lengthy answer, and I haven't had an opportunity to test all the code (in fact I'm fairly positive I made a mistake somewhere) - don't hesitate to ask questions. My other advice is to understand the concepts thoroughly, and then write your own code one bit at a time.
Good luck!
The way I would do this is to design an individual hit test for each block he will be picking up, then code for the hit test to play a frame within the sprite's timeline of him carrying a block, and to play a frame within the block to be picked up's timeline of the block no longer at rest (disappeared?).
Good Luck if you're confused about what I've said just ask a little more about it and I'll try to help you if I can.

Objective C - one button with multiple sequential outcomes

I am new to programing so any help is appreciated. I am trying to find the method for the following. I need one button that will, when executed, perform a different task in a sequence when activated. For example the first time that the button is pressed, I would like it to act as if the user is confirming the information in the title of the button (i.e. confirms that the user is older than 45). The second time that the user presses the button it confirms the response in the negative (i.e. confirms the user is NOT older than 45). The third time the user presses the button the field is reset and no value has been assigned (i.e. it is as if the user never answered the question).
For real-estate purposes I would like the information in question to be the title of the button and update appropriately once the action has been captured. For example, if the action is positive the display is shown with a circle around the title. If the action results in a negative response, the title is shown with a line through it.
I have done quite a bit or reading to try to get a solution but no dice so far. I have tried overlaying a button on a label with the text of the label changing, but so far I am not having any luck
I can't imaging that this is a unique issue and any help is appreciated. Much thanks in advance.
On the event just have some code like this
Header
- (IBAction)buttonPressed:(id)sender{
static int counter;
if (counter == 0){
// do stuff for first time Example [sender setTitle:#"45"];
}else if (counter == 1){
// do stuff for second time Example [sender setTitle:#"-45"];
}else if (counter == 2){
// do stuff for the third time
}
counter += 1;
if (counter > 2){
// restart the counter
counter = 0;
}
}