Theoretically, when I touched an enemy I would lose one life and from three hearts I would have 2. What happens is that when I collide with him, the lives are all lost restarting the room because I have to when I reach 0 lives, the room restarts. I'm using GMS2 and using GML, I don't know anything about DnD... Here´s my code to collision with enemy:
//create event
global.lifes = 3
//collision event
global.lifes -= 1
You'll need to implement an invulnerability function, that'll prevent the player character from getting damaged again on the next frame.
The most simple one would be a timer that counts down if you got hit, and if that timer is still counting down, then ignore the Collission Event.
See also my answer here about adding invincibility in GMS2:
https://stackoverflow.com/a/62769522/2735344
Related
I'm trying to make a game where spikes fall from the sky and the player has to move from side to side to dodge them. The object I'm trying to get to move down from the top of the screen is named obj_spike. What I want to accomplish is the spikes spawning in at the top of the screen and moving downwards. This works if I put the objects in the room as they are, but I can't make it spawn infinitely. How do I do that? The piece of code I've been trying to use is this:
instance_create(random_range(0,640),480,obj_spike);
For some reason the object just doesn't create.
I'm working on a 2D shmup, and the idea is that the level continuously scrolls automatically, and your character can move around the screen.
Now, I'm having trouble figuring out how I would implement this and Google hasn't been any help. Right now I have a scrolling background (the background position is simply decremented for each frame) and the player can move around freely in the window, but how would I go about creating the objects in the level? Would I just use a timer to trigger objects and enemies or is there a way to do it based on the position/width of the background (I'd prefer the second method...But I have no clue how that would be done)?
Since this is a general question and doesn't really pertain to any of my code that I've already written as far as I know, I don't think I need to include any of it...But I'll be happy to provide any part of it if needed.
I'd recommend either:
Use physical triggers
Use a list of timed events
Physical triggers
Simply place a box on your level. When it scrolls partially or completely onto the screen (whichever makes more sense - maybe use both in different cases?), you trigger the event associated with that trigger.
This would be simpler to support in a level editor because the physical nature is inherently very easy to visualize.
Timed events
You basically create a timer object at the beginning of the level, and an ordered queue of events. In your game update loop, peek at the head of the queue. If the trigger time of the item at the head of the queue is less than the current elapsed time, pop the item off the queue and trigger the event.
Timed events would be more generically useful because it would also support non-scrolling level, or non-scrolling portions of levels.
Combination of both
You could also do some sort of combination of these to get the benefits of both styles: Easier visualization/level editing, and supporting non-scrolling sections or time-based events.
Each physical trigger will have its own script queue. When the trigger is hit, a timer is started and an event queue is created. That timer and queue is added to a list of currently running timers and queues.
In your update function, you check all items on the list, and trigger events the same way you did with the timed event queue above. Once a queue is emptied, you remove it from the list of timers/queues.
How to detect that a trigger is on-screen
You should implement scrolling first.
One you have scrolling, calculate the rectangle that matches where the screen is located in your pixel/world coordinate system. This will give you the "bounding box" of the screen.
From here, do an intersection test between your event trigger's "bounding box" and the screen.
Here is a test to see if there is any overlap between two rectangles. It isn't order-specific:
rect1.left < rect2.right && rect1.right > rect2.left
&& rect1.top < rect2.bottom && rect1.bottom > rect2.top
If the rects are touching at all, it will return true.
Here is a test to make sure rect1 contains rect2. Order is important:
rect1.left <= rect2.left && rect1.right >= rect2.right
&& rect1.top <= rect2.top && rect1.bottom >= rect2.bottom
If rect2 is completely contained by rect1 (it is completely on-screen), it will return true.
How to implement simple timers
Simply get some sort of clock value (could be SDL_GetTicks), and store that value.
To see how long has elapsed since that timer was started, call the function again and subtract. Compare the values with < to see if the difference is greater than the target time.
Unfortunately, this is where you should use pointers. Something along the lines of:
vector<BadGuy*> Listofbaddies;
//Place enemy just off screen
newYposition = SCREEN_HEIGHT + 20;
//an infinite (almost) amount of badguys can be created with this code:
Listofbaddies.push_back(new Badguy(newXposition,
newYposition,
EnemyType,
blahblah);
Which means that the badguy will need a constructor like:
Badguy::Badguy(float newX, float newY, string Type, whateverelseyouwant){
actualSpritePartOfBadguyClass.setPosition(newX, newY);
}
Does that make sense? I'll elaborate if you ask :D
I'm making a game now that uses something similar :)
I have a limited area (screen) populated with a few moving objects (3-20 of them, so it's not like 10.000 :). Those objects should be moving with a constant speed and into random direction. But, there are a few limitation to it:
objects shouldn't exit the area - so if it's close to the edge, it should move away from it
objects shouldn't bump onto each other - so when one is close to another one it should move away (but not get too close to different one).
On the image below I have marked the allowed moves in this situation - for example object D shouldn't move straight up, as it would bring it to the "wall".
What I would like to have is a way to move them (one by one). Is there any simple way to achieve it, without too much calculations?
The density of objects in the area would be rather low.
There are a number of ways you might programmatically enforce your desired behavior, given that you have such a small number of objects. However, I'm going to suggest something slightly different.
What if you ran the whole thing as a physics simulation? For instance, you could set up a Box2D world with no gravity, no friction, and perfectly elastic collisions. You could model your enclosed region and populate it with objects that are proportionally larger than their on-screen counterparts so that the on-screen versions never get too close to each other (because the underlying objects in the physics simulation will collide and change direction before that can happen), and assign each object a random initial position and velocity.
Then all you have to do is step the physics simulation, and map its current state into your UI. All the tricky stuff is handled for you, and the result will probably be more believable/realistic than what you would get by trying to come up with your own movement algorithm (or if you wanted it to appear more random and less believable, you could also just periodically apply a random impulse to a random object to keep things changing unpredictably).
You can use the hitTest: method of UIView
UIView* touchedView=[self.superview hitTest:currentOrigin withEvent:nil];
In This method you have to pass the current origin of the ball and in second argument you can pass nil.
that method will return the view with which the ball is hited.
If there is any hit view you just change the direction of the ball.
for border you can set the condition for the frame of the ball if the ball go out of the boundary just change the direction of the ball.
First of all, I know there are a few other StackOverflow questions about this subject, but I have read them all and I still am confused about what to do for my situation. I'm probably missing something obvious here, if you could help clarify that would be much appreciated!
I have a app which is doing a lot of work to animate images within a view - mainly comprised of a number of images moving in straight lines for a second or two at a time. I considered at first making them all simple, once off animations using UIView animateWithDuration for the whole duration of the movement. But I found that didn't give me a lot of power to intercept the movement or stop it or check where it was up to, so I scrapped that. My new approach is to use an NSTimer, firing 20 times per second, doing incremental movements. This way I also can intervene (almost) instantly to change the animation or stop it or update a status label based on how far through it is, etc, etc.
First of all...there probably is a better way than this. Feel free to suggest something better!
Assuming this is acceptable though, my issue now is that while these animations are happening, I can't click any of the other controls on the UI. I get no response. It's not like it's just slow or delayed either - the click never comes through. It seems that the NSTimer processing totally locks the UI - but only from new interactions. Changes I make to the UI within the timer processing method happen just fine, and are very snappy.
From what I've read this shouldn't happen. However I also saw a comment on this question saying that if the timer processing is intensive then it could lock the UI thread. I don't see my processing to be that intensive here - certainly no resource requests, just a bit of data manipulating and animating some objects - but I could be underplaying it.
What are my options here? At first I thought I might create a new thread to kick off the timer. But I remember reading that the UI updates have to happen on the main thread anyway. Why is this? And plus, would that really solve the issue? Am I just asking too much of the device to process this timer as well as UI interactions? Is there something else I'm missing?
Any and all advice would be appreciated.
Edit:
I've just found the cause of my UI blocking problem. I was using the animateWithDuration with blocks, but was not setting the options. Therefore UIViewAnimationOptionAllowUserInteraction was not set. I changed it to set this option and my UI is happily responding now.
That said, I'll still leave this question open for specific suggestions regarding my overall approach. Thanks.
I would consider using CADisplayLink. From the documentation:
A CADisplayLink object is a timer object that allows your application to synchronize its drawing to the refresh rate of the display.
Your application creates a new display link, providing a target object and a selector to be called when the screen is updated. Next, your application adds the display link to a run loop.
Once the display link is associated with a run loop, the selector on the target is called when the screen’s contents need to be updated. The target can read the display link’s timestamp property to retrieve the time that the previous frame was displayed. For example, an application that displays movies might use the timestamp to calculate which video frame will be displayed next. An application that performs its own animations might use the timestamp to determine where and how displayed objects appear in the upcoming frame. The duration property provides the amount of time between frames. You can use this value in your application to calculate the frame rate of the display, the approximate time that the next frame will be displayed, and to adjust the drawing behavior so that the next frame is prepared in time to be displayed.
Your application can disable notifications by setting the paused property to YES. Also, if your application cannot provide frames in the time provided, you may want to choose a slower frame rate. An application with a slower but consistent frame rate appears smoother to the user than an application that skips frames. You can increase the time between frames (and decrease the apparent frame rate) by changing the frameInterval property.
When your application finishes with a display link, it should call invalidate to remove it from all run loops and to disassociate it from the target.
CADisplayLink should not be subclassed.
I'm not totally sure how everything is handled in your program, but you might want to just consider having one thread/timer that controls all of the objects and their movements. There's really no need to create a separate thread/timer for every single object, as that will easily cause problems.
You can just create a class for your moving items with some variables that contain information about their direction, speed, duration, etc, and then have a controlling thread/timer calculate and move the objects. You can then intervene onto the one main controller object instead of having to deal with many other objects.
I think you'll find that even if you optimize this, timer based animation like this is not going to perform well.
You might want to ask about the specific things that you think you couldn't do with CoreAnimation. If you solve those issues, you'll end up with a much better result than trying to roll your own.
I'm trying to play a "boing" sound when a ball shape hit's any other kind of shape. Which works. But works a little too well....
When the ball comes to rest, or starts to roll, it's in a permanent collision with whatever it's touching, so the "boing" sound fires constantly.
I can't find anything in the chipmunk documentation to tell me when two things are permanently colliding. So I'm thinking I will have to somehow figure it out myself, probably with some sort of timer that compare the last collision against the current collision. But that sounds hacky to me.
Has anyone tackled this issue? How did you solve it?
Couldn't you just play your "boing" sound when contact is BROKEN?
There is a callback for that in chipmunk, typedef void (*cpCollisionSeparateFunc)(cpArbiter *arb, struct cpSpace *space, void *data)
That way you get boings whenever it bounces, but not when it's just rolling along. 'course, you'll also get one when it rolls off of your shape, but that could be a feature depending on how you look at it.
I don't think that what I'm about to say is a good practice, but I'm sure it will solve your problem:
For each object, keep two state variables: (1) The last object collided with, (2) The last collision time.
Upon collision, only play a sound if the collided object is different (and a ball) OR a certain "delta time" has elapsed since the last collision. Then record the last collision stats.
This is pretty simple and very effective:
// In your ball interface
id lastCollisionObject;
double lastCollisionTime;
// When a collision occurs...
double now = GetTime();
id other = GetCollisionObject();
if ((now - lastCollisionTime) > 0.3 || other != lastCollisionObject) {
PlaySound(kBoingSound);
}
lastCollisionObject = other;
lastCollisionTime = now;
Shapes don't have velocity in chipmunk. The bodies they are attached to have it. You can access velocity like this: "myShape.body->v". I agree that you should just be able to check if the velocity is over a certain threshold to know when an 'impact' occurs. You can also check the rotational velocity to see if the ball is rolling.