Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Would someone be able to give me an example how to change the texture drawn when the user pressed the keyboard ?
Basically I have 5 sprite images stood still, up, down, left, right
My first attempt was to make boolean conditions in the update method such as if keys.left is pressed the rectangle moves left and for the draw method to draw the character moving left, my problem is the texture of him stood still doesnt disappear and overlaps the same when moving in different directions.
I've tried else statements etc but I'm stuck on basic movements.
So this is very pseudo code, but this is a basic approach how to do that
First we create class which contains all our informations about the player. You can add Health, Score etc aswell.
class Player
{
Texture2D Sprite;
Vector2 Position;
Vector2 Velocity;
static const float PlayerSpeed = 5;
}
Important here is the Position (top left of the sprite), the Velocity(the amount of change every second) and the sprite which is just our texture we want to use. Of course it would be better to use only one player texture and modify the source rect accordingly.
Now our input handling.
void OnKeyboard(GameTime aGameTime, KeyArg aKey)
{
if(aKey == Keys.Left)
{
mPlayer.Velocity = new Vector2(-Player.PlayerSpeed, 0);
mPlayer.Sprite = TextureManager.GetTexture("left_player");
}
else if(aKey == Keys.Right)
{
mPlayer.Velocity = new Vector2(Player.PlayerSpeed, 0);
mPlayer.Sprite = TextureManager.GetTexture("right_player");
}
mPlayer.Position += aGameTime.EllapsedMiliseconds * mPlayer.Velocity;
}
Here we just check which key was pressed, modify the velocity and change the current sprite for our player. The final line is the most important one, this modifies the players position using the velocity modified by the elapsed time of the frame. That way you have a steady movement instead despite any frame rate inconsistencies.
void Render()
{
Sprite.Draw(mPlayer.Sprite, mPlayer.Position);
}
Finally the rendering, how to render a sprite should be clear, here you just use the set sprite and the position.
There is a lot of room for improvements, for example minimizing texture switches, handling sprites with alpha, and the most important one proper handling of the keyboard. You need to steadily adjust the position, but depending on how you implement it, the movement might be bound to the key repeat rate, which may not be desired.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
I'm trying to make a volume knob like this:
https://s-media-cache-ak0.pinimg.com/736x/29/b5/85/29b58559e3d8a09dcd7e1a47c700ca76.jpg
But I only want to use one finger, UIGestureRotate is great but only supports rotation with two fingers and I don't seem to find the solution for UIPanGestureRecognizer to rotate as I want it to? Is there a simple way to simulate the second finger in rotategesture or do I have to calculate pan?
If you ignore gesture recognizers and override touches handlers on a view, you can use math to do this. With a little trig, take an arbitrary anchor point along an axis (say 9 o'clock on the knob), and your touches' locations on the plane with (0, 0) at the center of your knob. Say your anchor point is at (-3, 0) and your touch is at (-1, 1) for the sake of simplicity. Take the arctan of the change in y over the change in x, in this case arctan of 1/2, which is roughly 0.464 radians, or roughly 26.585 degrees. You would rotate your knob 26.6 degrees clockwise (in this case) from your anchor point to have your knob follow your touch. In Swift:
//Assume you have an anchor point "anchor" and a touch location "loc"
let radiansToRotate = atan2(loc.y - anchor.y, loc.x - anchor.x)
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotateAnimation.fromValue = 0.0
rotateAnimation.toValue = radiansToRotate
rotateAnimation.duration = 1.0 //the longer the duration, the "heavier" your knob
That rotate animation will make the knob "follow" your finger, the desired effect. For completeness' sake, in a very basic form, atan2 is a math function that protects you from undefined arctan values. You'll have to worry about rotation direction, possibly, if your values fluctuate wildly, so you may consider using a key frame animation for this (I'll leave this to you).
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I am trying to apply a sort of impulse onto a sprite and have it thrown onto the screen from the side. However, when it is after the screen I want the impulse to stop and for the regular physics to be applied to it, so I would be able to drag it around. Its difficult to explain but if anyone can help out it would be very much appreciated. Thanks!
Apple docs show that a we can influence the physicsBody of a sprite with these instance methods:
- applyForce:
- applyTorque:
- applyForce:atPoint:
- applyImpulse:
- applyAngularImpulse:
- applyImpulse:atPoint:
As for "throwing it on the screen from the side", you can have the sprite spawn outside your current skViews bounds, and have the force be applied to it accordingly (if the sprite is located outside the north side of the screen, you'll want to applyImpulse downward).
With respect to "regular physics" upon entrance of the skView, you can have a check in update:(CFTimeInterval)currentTime for those types of sprites entering the skViews frame OR define a protocol within your sprite's class, and have your SKScene subclass conform to that protocol; then have your sprite fire a method when entering a certain frame (skView.frame), which your SKScene will be able to respond to. You can then apply counter forces or impulses to that sprite.
I'm building a Mega Man clone for a school project and I just finished the code to make my character jump and it works perfectly. But I need it to display the actual jump sprite of Mega Man. This is the whole code in Game1:
http://pastebin.com/py7Y7mtD
The AnimatedSprites jt helps you decide the direcrtion and display the sprite. Doesn't matter right now if it's efficient. It's just for starts. When I'll get to more complex stuff I'll work on it.
MegamanJump has the jump sprite(5 or 6 sprites displayed from left to right)
MegamanJump_Flip is the same thing but to the left(again, forget about efficiency).
Basically you want to switch out the current drawable sprite with the sprite you want to draw depending on moving direction or moving direction + jump.
Since you already have a running update method, all you have to do is write another method that does this for you, a state variable to track what is happening and the actual states it can have, preferrably in an enum for clarity.
Essentially
private void swapSprite() {
if(state == CharacterState.LEFT) {
sprite = leftDrawable;
}
//etc other single ifs
if(state == CharacterState.LEFTJUMPING) {
sprite = leftJumpDrawable;
}
}
Change the states on button press combinations, call this method after checking for movement.
I hope this helped!
I have my first game application in development. In this game, the only character that the user controls will get to jump from one block to another. It's like Mario (in Mario Brothers) jumping from one moving lift to another. If he fails, he'll die. So how could you tell a free fall from a short fall as a result of a successful jump? One thing I thought I could do is measuring character's vertical velocity. So I have the following lines of code. It's used with didSimulatePhysics
SKNode *player = [self childNodeWithName:#"//player"]; // It's the node characterizing the game character
CGVector v = player.physicsBody.velocity;
if (v.dy < -2000) {
[self endTheScene:kEndReasonLose]; // The character has died from free fall => game is over
}
When the game character jumps, the game application can record a vertical velocity of -2022.466797. So this measure won't work. What else can I do? Set an invisible bar and see if the game character has touched it with intersectsNode? That can also fail. I have never developed a game before. So I don't know how they do it, which kind of makes me realize how impressive Nintendo game developers are. Some 30 years later, I still can't do it.
Thank you for your advice.
Update
The following can tell whether or not the character has died from free fall, I think.
- (void)didSimulatePhysics {
if (self.isMoving) {
// isMoving is an instance variable (BOOL): YES if the game has started
CGVector v = player.physicsBody.velocity;
BOOL hasFallen = self.lastFallenDate ? [self.lastFallenDate timeIntervalSinceNow] < -2.0 : YES; // lastFallenDate is an instance variable recording the time when the character fell last time
if (hasFallen) {
if (v.dy < -1500) {
[self endTheScene:kEndReasonLose];
}
}
}
}
Yet, I think Apple has a bug to fix as far as SKAction is concerned. No matter I do, audio will kick in exactly about 5 seconds after the game started although the character is not falling.
- (void)endTheScene:(EndReason)endReason {
if (endReason == kEndReasonLose) {
SKAction *lossAudio = [SKAction playSoundFileNamed:#"failureAudio.caf" waitForCompletion:NO];
[self runAction:lossAudio];
}
}
Super Mario Bros was a tile-based game: the screen was divided up into a number of square regions each of which being represented by a value. Each tile would have a separate sprite blitted to that region of the screen depending on the tile id, and based on that tile's properties Shigeru et al could determine if mario could stand on it, if it would hurt him or if he was free to fly. There's no magic to this, you just have to check where he is!
If you aren't concerned with the damage your Mario will take (i.e can he land a jump from any height as long as it is onto solid ground) this is easy: If his y position is ever lower than the lowest solid platform in your world, he has died:
Ignore velocity; check y position.
If you don't want him to survive a jump from the top of a building, you need to look at his velocity: Is he travelling fast enough that the force of impact would end his life?:
Ignore y position; check velocity
How do you know he is on a platform? A physic node?
Honestly, you can put a 'floor' plane stretching your world and anchor it at the bottom of your scene to catch dying plumbers and it won't impact performance - infact it will be more efficient than running these checks in your Update method.
Edit to add
Don't bother with intersections, -(void)didBeginContact:(SKPhysicsContact*)contact will alert you to any collision that occurred as long as you are a delegate. Skip the update loop completely: this will trigger for any collisions and won't be missed
I need the user to be able to drag and drop several pictures(sprites). However, I do not want them to overlap with each other. I plan to add something in the 'onTouchEnded' method but do not know how to do it.
The preferred way is to only change the overlapping part of the two sprites to red-tinted. However, if this is not possible, we can also change the two sprites both to red-tinted.
I tried to use sprite.color = ccRED. but it changed the whole sprite to red color instead of a tinted one.
By the way, both the two sprites are in regular sizes.
Simple way is you can check colliding of two sprite
if( CGRectIntersectsRect( [sprite1 boundingBox], [sprite2 boundingBox] ) ) {
// Handle overlap
}
You This logic in your case :
Also i got it from This Link.
Yes, it should… though it might look a little weird, depending on how exactly your sprites are shaped. You can also try testing for distance, which works better if your sprites are more circular:
// This is how close the sprites have to be for the game to think that they're colliding
// (or overlapping). Use a smaller value than 0.5 if you want them to be closer together
// in order for there to be a collision.
float distanceForCollision = (sprite1.contentSize.width * 0.5) + (sprite2.contentSize.width * 0.5);
// This is how close the sprites actually are
float actualDistance = ccpDistance( sprite1.position, sprite2.position );
// Check if they're close enough
if( actualDistance <= distanceForCollision ) {
// Handle overlap
}
Both methods work really well, but like I said… it might look a little strange, depending on the shape. Testing for collision/overlap with, say, star-shaped sprites would look a little weird using either method. Still, for menus and drag & drop, it should be enough.