Squashed Sprite when turning horizontally - animation

Unsquashed Sprite Squashed Sprite
My brother has issues with his sprite squashing whilst moving horizontally. The squashing is permanent after moving. I have found the line that causes the problem but cannot figure out what is causing this issue. When I remove this line the squashing stops however the sprite does not turn. He is following Shaun Spalding's Complete Platformer Tutorial and though I've watched it over I cannot find any issues with the actual code.
/// #description Insert description here
// You can write your code in this editor
// get player input
key_left=keyboard_check(vk_left);
key_right=keyboard_check(vk_right);
key_jump=keyboard_check_pressed(vk_up);
// calculate movement
var move=key_right-key_left;
hsp=move*walksp;
vsp=vsp+grv;
if(place_meeting(x,y+1,o_wall)) and (key_jump)
{
vsp=-7;
}
// horizontal collision
if (place_meeting(x+hsp,y,o_wall))
{
while(!place_meeting(x+sign(hsp),y,o_wall))
{
x=x+sign(hsp);
}
hsp=0;
}
x=x+hsp;
// vertical collision
if (place_meeting(x,y+vsp,o_wall))
{
while(!place_meeting(x,y+sign(vsp),o_wall))
{
y=y+sign(vsp);
}
vsp=0;
}
y=y+vsp;
// animation
if(!place_meeting(x,y+1,o_wall))
{
sprite_index=splayerA;
image_speed=0;
if (sign(vsp) > 0) image_index = 1; else image_index = 0;
}
else
{
image_speed=1;
if (hsp==0)
{
sprite_index=s_player;
}
else
{
sprite_index=splayerR;
}
}
if (hsp != 0) image_xscale = sign(hsp); //this line is wrong and causes the squishing

A possible cause of this is that you've set the image_xscale to a different value before using the line:
if (hsp != 0) image_xscale = sign(hsp);
For example, you may have set this in the Create Event to enlarge the sprite:
image_xscale = 2;
But that value is reset after setting image_xscale again, as that line will only return -1 or 1 because of the Sign().
One quick solution is to apply the scale change to that line of code, like this:
if (hsp != 0) image_xscale = 2 * sign(hsp);
(Once again, presuming you've changed it's scale value somewhere else)
Though another solution is to enlarge the sprite itself in the sprite editor, so the scale doesn't have to be kept in mind everytime.

Related

How can I ensure the missile stays on the screen when non-spacebar keys are pressed?

I need to write a Processing program so that "When the user presses the space key a missile is fired from the front of the ship and moves rightwards until leaving the screen. The user can't fire another missile until the first is off the screen."
What I have written doesn't allow the missile to stay on the screen if other keys are pressed. I have tried adding the function under void keyPressed() with boolean true/false statements which only stopped the whole program from working.
How can I make sure it stays on the page? Also, how can I make sure the player can't shoot another missile until their previous one moves off the screen?
This is the code I have:
//global
int ship_y;
int angle;
int missileX;
void setup(){
size(500, 500);
ship_y = 10;
missileX = 55;
}
void draw(){
background(175);
fill(50);
rectMode(CENTER);
rect(30, ship_y, 50, 25);
//missile moves rightwards after spacebar is pressed
if (key == ' '){
circle(missileX, ship_y, 25);
missileX = missileX + 1;
}
}
//ship moves down when 's' is pressed and up when 'w' is pressed
void keyPressed(){
if (key == 's'){
ship_y = ship_y + 2;
}
if (key == 'w'){
ship_y = ship_y - 2;
}
}
Code within the draw() function runs every frame.
So every frame, you're clearing the background, drawing the ship, and drawing the missile. Good.
But.
You put the missile drawing code inside this if statement:
if (key == ' '){
that only draws the missile if the most recent key pressed was space. So as soon as you you press a different key, key is no longer equal to space and your missile doesn't get drawn.
One way to fix it would be to create a variable to indicate whether or not the missile was fired, and use that to determine whether or not to draw the missile (instead of checking the key variable).
Like this:
if (missileFired == true){
circle(missileX, ship_y, 25);
missileX = missileX + 1;
}
Code inside the keyPressed() function only runs once each time a key is pressed. This would be a better place to detect when the spacebar is pressed and turn on the missileFired flag:
void keyPressed(){
// code for other keypresses...
if(key == ' '){
missileFired = true;
}
}
To detect when the missile goes off screen, you'll just need to check whether missileX is greater than the width of the window. draw() would be a good place for that, since you probably want to check for it every time the missile moves.
When missileX gets larger than the window width, you can reset missileFired to false so a new missile can be fired. You'll also need to reset missileX to its original position so it originates from the ship position.

My program appears to stop working

I am quite new to programming and decided to make a little game, so far I have only made a small block that is able to move in all 4 directions (left, right, up and down). Pretty simple and nothing extra-ordinary. However, when I run my program, sometimes it will stop working, not as in crashing causing Processing itself to crash, but my program will just end.
As far as my testing goes, I think this happens when I press two keys at the same time (like W and S). Does anyone happen to know what causes it to stop, and perhaps how to fix it as well?
void setup(){
size(1080,720);
frameRate(30);
}
int shipLR = 0; //Variable for the ship to go left/right
int shipUD = 0; //Variable for the ship to go up / down
void draw(){
background(0);
shipLR = constrain(shipLR, 0, 1040); //Constrain the ship in the window
shipUD = constrain(shipUD,0,680); // Constrain the ship in the window
move();
Shuttle();
}
void Shuttle(){
rect(shipLR, shipUD, 40,40); //Draw the ship
}
void move(){
if (keyPressed) {
if (key == 'a') {
shipLR = shipLR - 20; // Go left
return;}
if (key == 'd') {
shipLR = shipLR + 20; // Go right
return;}
if (key == 'w'){
shipUD = shipUD - 20; // Go up
return;}
if (key == 's') {
shipUD = shipUD + 20; // Go down
return;}
}
}
Any help will be greatly appreciated.
Edit: I found something that causes this problem to occur more frequent; If I implement a frameRate of a value lower than 60 (currently trying with 30) this happens more often.
Edit 2: With the suggestions below of making my move function in a single if block had a lot of good impact. The program no longer stops when I move the ship in the middle of the window it no longer stops, it now only does it at rare occasions when I bump too often against the borders of the window. Perhaps it has something to do with constrain?
in move() (java naming conventions specify that method names start with lower case) you should exit on the first key pressed found. the code can be re-organized to reduce multiple identical conditions:
void move(){
if (keyPressed) {
if (key == 'a') {
shipLR = shipLR - 20; // Go left
return;
}
if (key == 'd') { // still inside if keyPressed
shipLR = shipLR + 20; // Go right
return;
}
if (key == 'w') {
...
}
} // end of if keyPressed
}
My guess it that the program doesn't "stop working" or end- it's just that your rectangle stops moving. If you let go of all the keys, then push just one key, I'd bet that the rectangle starts moving again. (In the future, please try to be more specific- saying "it stops working" isn't very helpful.)
Anyway, that's because of the way you're handling the key presses. What happens if you press a key other than the ones you're checking for?
You'll enter the move() function, and you'll enter the if(keyPressed) block, but you won't enter any if the other if statements inside that block. The key variable only holds the most recently pressed key.
Depending on what you want to do, you should either refactor those if statements to only change the direction if the key was valid, and to ignore all other key presses. Or you might want to use a set of boolean variables to track multiple keys being pressed at the same time. More info on that approach can be found here.
If you still can't get it working, then please try to be more specific about exactly what happens.

Game Maker - Freezing an sprite on animation end

When the player dies, I want the sprite to stop animating on the last frame.
I tried this on Animation End event
if (sprite_index == spr_ninja_dead) {
image_speed = 0;
image_index = image_number - 1;
}
I also tried this
if (sprite_index == spr_ninja_dead) {
image_speed = 0;
image_index = 9;
}
This is the recommended way that GM suggests, yet the sprite freezes on the first sub image. What am I doing wrong?
When the player gets hit, the sprite would change to a flashing sprite image. Then an alarm would change it back to normal. I added an if statement to fix this:
if (sprite_index = spr_ninja_flash){
sprite_index = spr_ninja_idle;
}
What you want to do is run the animation first.
So try this:
if( sprite_index == spr_ninja_dead ){
if( image_index == image_number ){ // This will check if the image is the last image of the sprite
image_speed = 0;
}
}
First you check if the sprite is the dead one, then you check if it's the last image of the sprite and if that is the case you can pause the animation using the image speed.

Set position not updated when open another tab

I do a growth animation of a fixed number of items, and after growth, i moved it to left.
Make growth by apply matrix
var trans_vector = new THREE.Matrix4().makeTranslation(0, height / 2, 0);
var graphics = new Graphics();
var rectangle = graphics.box(width, height, material);
rectangle.geometry.applyMatrix(trans_vector);
When a new item is added, i remove one from the container that will be added to scene
var children = this.container.children;
if (this.current_number === this.max_number) {
this.container.remove(children[0]);
this.current_number = this.max_number - 1;
}
object.position.copy(this.position); // this is a fixed position
this.container.add(object);
this.current_number++;
I write a function to translate to left, using tweenjs (sole)
animateTranslation : function(object, padding, duration) {
var new_x = object.position.x - padding; // Move to left
console.log(new_x); // Duplicated item here :(
new TWEEN.Tween(object.position).to({
x : new_x
}, duration).start();
},
And I remove all the "previous" items, using for loop
for (var i = 0; i < this.current_number-1; i++) {
this.animateTranslation(this.container.children[i],
this.padding,
this.duration/4)
}
The above code run correctly if we open and keep this current tab.
The problem is when we move to another tab, do something and then move back, some objects have the same position, that cause the translation to the same position. It looks weird.
It appears on both Chrome, Firefox and IE11.
I dont know why, please point me out what happened.
Most modern browsers choose to limit the delay in setInterval and pause requestAnimationFrame in inactive tabs. This is done in order to preserve CPU cycles and to reduce power consumption, especially important for mobile devices. You can find more details about each browser in this answer
That means, while the tab is inactive, your tween animation is not working the way it is normally expected to.
A simple solution would be to halt the main animation loop if the tab is inactive using a variable.
window.onfocus = function () {
isActive = true;
};
window.onblur = function () {
isActive = false;
};

Using scrollViewDidScroll with multiple UIScrollViews

I have two horizontally scrolling UIScrollViews stacked vertically on top of each other within one ViewController. Each UIScrollView takes up half the screen. I am trying to independently track the position of both UIScrollViews.
I have successfully used this to track the position of the top UIScrollView:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView1 {
int Position = (scrollView1.contentOffset.x);
if (Position == 0) {
NSLog(#"Play A");
}
else if (Position == 280) {
NSLog(#"Play B");
}
//etc.
}
I would like to track the position of the bottom UIScrollView as well.
When I try to use this:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView2 {
int Position2 = (scrollView2.contentOffset.x);
if (Position2 == 0) {
NSLog(#"Play A2");
}
else if (Position == 280) {
NSLog(#"Play B2");
}
//etc.
}
I get an error that says "Redefinition of FirstViewConroller scrollViewDidScroll".
So, determined to press on, I tried a rather hackish solution and attempted to use this instead:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView2
{
int Position2 = (scrollView2.contentOffset.x);
if (Position2 == 0) {
NSLog(#"Play A2");
}
else if (Position2 == 280) {
NSLog(#"Play B2");
}
//etc.
}
The problem with this is that it triggers both methods when I move either of the UIScrollViews. For example -- if I move the bottom UIScrollView 280 pixels (one image) to the right, the output I get in the console is:
PlayB
PlayB2
And if I move the top UIScrollView three images to the right the output I get is:
PlayC
PlayC2
Which doesn't make any sense to me.
I think I may be bumping up against my own incomplete understanding of how delegates work. Within the viewDidLoad method I am setting both:
scrollView1.delegate = self;
scrollView2.delegate = self;
Perhaps this is part of the problem? Maybe I am causing trouble by declaring that both scrollViews have the same delegate? Just not sure.
I've also tried combining all of my conditional statements into one method -- but I only want to track the position of the bottom UIScrollView when it moves and the position of the top UIScrollView when it moves, and putting the logic all in one method reports both positions when either one moves and this is not what I'm looking for.
Any help is appreciated. Would love to solve this particular problem, but would also really love to understand any bigger issues with how I'm approaching this. Still new at this. Keep thinking I'm getting the hang of it and then I run into something that stops me in my tracks..
This is exactly what the UIScrollView parameter is for. Create connections to scrollView1 and scrollView2 in IB and then do this:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (scrollView1 == scrollView) {
// Do stuff with scrollView1
} else if (scrollView2 == scrollView) {
// Do stuff with scrollView2
}
}
There's no reason why the same object can't be the delegate of several different scrollviews. The reason that -scrollViewDidScroll: passes you the scrollview in question is so that you know which scrollview did scroll.
This is the general pattern for delegate messages.

Resources