This thread is my Q&A for some game maker technical questions, and
I'm gonna summarise what's been solved in this thread in this first post so that it may help others answer some GM Studio questions.
[Solved]
Screen Shake code is wonky
How to get PS3 or xbox360 gamepad working in GMS
Gamepad code makes GMS speed drop to like 2 fps
Version control in GMS - use or not?
Offsetting mouse position to screenshake!
As yet unsolved
Original post-----------------------------------------
Hi guys
Just been doing some screen shake in my game (BEST EFFECT EVER) and I've found that after a while the screen doesn't centre back to the original view anymore, and I can't figure out how or why it's doing that... Mind looking at my code to gimme some pointers?
Much much appreciated!!!
The code runs on every step, and I set global.screenshake so that the bigger the value the longer and bigger the explosion.
I'm gonna summarise what's been solved in this thread in this first post so that it may help others answer some GM Studio questions.
[Solved]
Screen Shake code is wonky
How to get PS3 or xbox360 gamepad working in GMS
Gamepad code makes GMS speed drop to like 2 fps
Version control in GMS - use or not?
Offsetting mouse position to screenshake!
As yet unsolved
Original post-----------------------------------------
Hi guys
Just been doing some screen shake in my game (BEST EFFECT EVER) and I've found that after a while the screen doesn't centre back to the original view anymore, and I can't figure out how or why it's doing that... Mind looking at my code to gimme some pointers?
Much much appreciated!!!
The code runs on every step, and I set global.screenshake so that the bigger the value the longer and bigger the explosion.
// shaker if(global.screenshake > 0) { amounty1=-(global.screenshake/2)+round(random(global.screenshake)) amountx1=-(global.screenshake/2)+round(random(global.screenshake)) view_yview[0]+=amounty1 view_hview[0]+=amounty1 view_xview[0]+=amountx1 view_wview[0]+=amountx1 global.screenshake -= 2; } else { view_yview[0] -= (view_yview[0]/2); view_xview[0] -= (view_xview[0]/2); if (view_yview[0] < 1) and (view_yview[0] > - 1) { view_yview[0] = 0; } if (view_xview[0] < 1) and (view_xview[0] > - 1) { view_xview[0] = 0; } } // /shaker
Comments
Also, a simpler way to do screen shake is:
Step Event:
A larger value of shakeIntensity will have a inteser shake.
When you set canShake to true, also set an alarm for the period you want the screen to shake. In the alarm event set canShake to false and view_yview[0] to 0.
Also, I usually only shake in the vertical axis because it's easier to play with.
I'd like to get some multiplayer going so I can test my game but mine has analogue input so it needs two controllers (or port prototype to touchscreen), and it would seem two controllers with analogue stick is the easiest...
After some googling I've not found anything conclusive, according to the documentation in app gamepad_get_description seems to get the type of controller, and it uses a PS3 controller as an example, but I'm not sure if it's a simple matter of plug-n-play for game maker? Do I need any special DLLs to make it work? (a few threads stated as such but I haven't found anything specific...)
Thanks guys :D
It says it's similar to touch controls which means the first controller is device 0 and the second is device 1. So when you use the functions say: gamepad_axis_value(0, gp_axislh) for the first controller and: gamepad_axis_value(1, gp_axislh) for the second.
Then there's the question of whether if you just plug in the PS3 controller, and ask game maker nicely it'll just bypass the windows drivers' non-response and just magically work, somehow I doubt it.
Will be doing more investigation with the 360 controller as well... Although anyone with experience in this is more than welcome to chip in :D
For anyone who also am going to try gamepads in GMS:
1. A 360 wireless controller with the charger cable in will not be picked up as a proper controller. You need the WIRED one, or the official 360 controller wireless receiver.
2. The PS3 controller will only work in GMS if you use MotionJoy to emulate a 360 controller. To get the PS3 gamepad working, follow these instructions precisely: http://www.motioninjoy.com/wiki/en/install/latest
3. Then do a test in GMS with gamepad_is_connected(0) which should return true if working.
YAY!!! :D
So just as soon as I thought my gamepad controls are implemented and working, the whole game goes into chug-chug lag mode at less than half the usual framerate/speed. So I google around a bit and it seems like Game Maker has always had a history of a bug where gamepads will put the game into over-stress and lag it out. Sometimes it's when you had a gamepad in, or sometimes it's when you plug one out, etc.
I'm gonna have to just work around that, apparently. Looking into it... Hope anyone else may have some suggestions?
OMG...
My research landed me on people who say the best one can do is to make the game check for a gamepad existing before actually making gamepad calls, and each time one's supposed to make gamepad calls, refer to that check before making the call.
But this was in GM 8.1 apparently! I can't believe they haven't solved this by now...
I'm not by my game at the moment so can't try and implement but I'll give it a shot as soon as I can.
The slowdown when asking a gamepad that doesn't exist for information actually makes sense if you think about it: All peripherals are based on polling, so your program goes "Hey, gamepad, tell me what's going on!" and then waits for the gamepad to send it some information back. The reason your program has to wait is because the gamepad could be disconnected at any point - the cable could come out, it could run out of battery, it could be inexplicably placed inside a running microwave, etc. This means that every gamepad poll has a timeout after which the program assumes that the gamepad is just being slow or maybe not there and carries on executing. So all you're going to get happening when you keep asking a gamepad that isn't actually even there in the first place is a lot of timeouts, hence your game being slow while it waits for the call to timeout for every gamepad function you run.
So if it were predictable, I could deal with it, but it seems pretty random and out of my control. It hadn't happened all the way through my testing and trying out gamepad code - 2 or 3 days - it's only when I thought I finished it did it start to happen. WEIRD.
And the lag only ever affects GMS, I feel it might have to do with the compile and runtime rather than something else... I haven't done anything besides that emulator (which again worked fine at first for a long time while I was still building the controls).
Again, I'll have to experiment tonight and report back!
(I can't believe noone else has run into this before XD)
I found these on my research on the topic, I'll also try their advice out and see if it changes anything:
http://gmc.yoyogames.com/index.php?showtopic=567087
I was ALMOST about to give up, when I discovered the ONE THING that made the game return to un-lag - and that is to unplug the controller and re-plug it in, and re-enable the 360 controller emulation from DS3tool (that's the MotioninJoy Gamepad tool referenced above by squidcor).
I have NO idea why that works, only that it does. And I have to do this every time the game re-starts... or else it lags all over again. Well, hope this find helps the next frustrated GMS gamepad user!
Now I can finally get back to devving game mechanics rather than dumb controller bugger ups XD eventually i'll have to convert to touch controls anyway... eep.
I'm using an Xbox 360 Wired controller to connect.
I also got the lag when I started, so I grouped all the scripts together that checked for a gamepad input and only activated them if the gamepad is connected:
So:
This is more or less what @dislekcia suggested and it does seem to eliminate the lag :).
Now I have this in step:
And all gamepad code first checks global.gamepad_1_in before executing, which gave me the same results essentially...
But even with that, when the game starts it still will lag, until I unplug and plug in again. Maybe it's got to do with the MotioninJoy convertor. When/if I have a wired xbox controller I'll give it a go...
So I'm starting to need to branch my code to try different sorts of mechanics to prototype, should I use SVN and version control in GMS, or should I just be the one-man "team" that I am and use "save_as" and just pop out different files at various points when I know I'm stable?
I remember hearing horror stories about version control in GMS, is that true/still the case?
Thanks guys :)
Yay!
Bottom line: Swapping out objects that you simply don't use is a lot easier than messing with version control at this point of your life. Don't bother with version control until you have a team that absolutely has to share source.
So I have a screen shake system in place. And my game is controlled via mouse click and drag to set the angle of throwing stuff. Each frame, the game catches how much your mouse has moved, adds that to your angle, and resets the mouse cursor. This is my solution to the cursor falling off the screen sometimes. (Fullscreen will come later... And also I don't know how to make your cursor unable to leave the game, but that's another matter altogether)
So I finally got that to work, BUT... Now when I'm holding the angle of throwing, when something explodes and the screen shakes, it throws my angle out because the view change is registering as a change in device_mouse_x(0)...
I've tried to counteract it by modifying the power value by the value in the screen shake, but it's either "impossible" or I'm just missing something - it just doesn't work.
Can any kind soul please assist? XD
This is the mouse -> power code, on begin step:
input_event_hold_down is picked up by a mouse click and hold event.
(for some reason I set the mouse to 512,384, but if I set the offset in the calculation to that it doesn't zero... So it's offset by a bit, and I have NO IDEA WHY... XD But it works right now.)
And this is the screen shake code, on step (not begin step):
the bit I commented out are bits I tried to insert to offset the offset - if that makes sense... But it doesn't work at all.
I feel like there must be an easier way that doesn't get thrown by view_xview[0], but I don't know what it is... Is there?
Any assist greatly appreciated!
What this does is "undo" the movement of the screen from the mouse's perspective. The reason it didn't work the way you were doing it before is because the mouse was being moved by your command and then moved again when it actually checked the mouse's position. All you need to do is set amountx1 and amounty1 to 0 when whatever control object this is is created.
The code still has some drift, I don't know if it's because of something I'm missing, or if it's because the mouse detection happens before the shake (it's in a begin step, and the shake is in a regular step). In fact I don't know if both of them were in begin step which one would run first...
The detection needs to be in a begin step because I need the mouse values picked up before other steps access those values, and the shake isn't in a begin step object... Should I extract the shake into a begin step object? Does that make a difference?
I've got another idea, to use the absolute screen pixels that's unrelated to view - but it seems device_mouse_x(0) can't be unrelated to the view, and I'll need to use devices if this will eventually go to a touch device (that's the idea)...
OMG MY HEAD.
That should "remove" the view offset from the device's mouse co-ordinates that are being returned to you in game-space.
Looks so obvious when you do it XD Thanks a millllll!!! :D
How do I pass a variable NAME into a script as an argument?
like...
then in the script count_something
Then I do
Where argument0 is an array I'm going to fill with a for ~ do loop or whatever... Everything I try now results in the thing trying to pass the contents of block_array, and that's not what I want... I want it to take "block_array" as an array, not the content of the variable...
Research shows me... apparently you need "pointers" and you don't get those in GM?
Thanks again guys :D
There is another trick you can use, although it's super hax and blows encapsulation to pieces. I also don't know if it's been killed in Game Maker Studio or not. That is to create a user event in another object and call it using the event_user_other function. Game Maker will assume that the user event you're calling is within the scope of the script you're calling from, meaning that you can directly manipulate the variable by name.
Although, if you're using arrays like that and you're not sure how many things are in that array, why not either have a separate variable that's supposed to store the number of elements in that array (you'd increment it every time you added something) OR use lists?
A list is a structure for storing things, very similar to an array, that grows in size according to how many things are in it. You can easily pass around list identifiers, because you access lists (and other non-array GM data structures) like so:
Actual function names from memory, so may not be reliable. Check up the GM help... Anyway, reason lists are cool = you could go "Count_Something(myListPointer)" and it would actually make sense.
@Gazza_N I think that may be a way around, I'll have to check the structure of my script...
@dislekcia I think I haven't communicated what I need enough, what I want to do is have a function that can count instances of object X (variable) and put that into an array (variable). The size of the sample I'll also pass into the variable manually, but it's not the focus of the exercise.
So for example I'd call the script like this:
count_instance(obj_block, array_block_, 7, 14)
argument0 = the object type to count
argument1 = the array to put the count result into
argument2 = start with this x position
argument3 = end with this x position
So when I pass argument1 in it tries to take the content instead of the the variable name array_block...
The good news is there are totally ways to do this in GM, multiple ways, in fact!
The first solution to your problem is using the return keyword in a script. That means the script can ouput a value, so you can do something like myResult = someRandomScript(param1, param2, param3). That's really useful. Returning something will also stop a script running further, so you can totally do neatly optimised crap like:
Anyway, your options in GM are to either build a dummy object to use as a pointer location and store your results there - this object would have no sprites, no interactions and not really have any code. Or you could create a new ds_list to store your results in and then pass that around by identifier, which acts like a pointer. Doing things the list way is great if you want a single coherent set of results - all the x positions of a set of objects that are currently red, for instance - doing things the object way is better if you want multiple sets of results - all the colours AND x positions AND rotations of all the objects currently surrounded by the selection box... The important thing is to clean up after yourself and always delete the thing you created to store your results in when you're done using those results, otherwise it'll hang around forever.
Another thing to keep in mind is that if you really need a ton of results back from a script and think that means you should go the object route, there's probably a better way to go about solving your actual problem. Maybe you could create a dummy object that collides with the things you care about and performs the actions you want on them during its collision event, then kills itself. Maybe you could do all of that with a script that simply stepped through all the objects of a specific type and you didn't need to pass that info around to other scripts in the first place. Coding is fun like that :)
So, now that I understand your problem and you understand how I'm thinking about it, here we go:
You want a bunch of pointers to all the objects of a specific type that fall within a certain bounded area of the screen. We could totally build a dummy collision object to create that list, instead we'll just do the math on each object's position because that's faster and is available instantly.
You'd use it as follows:
So yeah. You could also keep that list around (or store it in a list of other lists or whatever) if you wanted OR you could easily modify the script above to take a specific list identifier you wanted the objects stored in as a parameter, but you would still have to clean it up eventually... This got a bit long, but I prefer explaining the logic behind a bunch of code, rather than just promoting copy-pasta. Hope that helps.
Is there a way to do localised collision detection with multiple instances of the same object, without stepping through ALL of the instances of the master object to collide with?
I got a pile of blocks, I want to see which ones are in collision with a certain area, but I imagine stepping through ALL the blocks would be expensive on the cycles if done a lot, so I'm trying to keep it lightweight...
Or should I really not be worrying about this kind of "optimisation"? XD
All the collision detection methods I know basically pick the "topmost" object and stops looking after that, even if a bunch of items are in the hit area.
Thanks ahead of time! Much appreciated! :D
But there are loads of ways to be more efficient if you need to, you could store blocks in a sorted structure, you could have a dummy object that built a list of blocks that it collided with and then only run through those blocks, you could even cycle through every block and only bother doing a collision test if they're close enough to the thing you're testing for.
But yeah, don't worry about that unless it's a real problem.
But yeah I'll worry about this another time, thanks :)
But then when I select the option to enter, it just hangs, not sure if it's loading without me knowing or if it just crashed... Can anyone shed any light on this?
https://dl.dropboxusercontent.com/u/15257303/game_dev/Prototype_1/index.html
Thanks!!
[edit]
Hmm... Are you sure that it's taking the command to enter? Looking at it again, having reloaded, I can click on an arbitrary part of the window (that's a rather pretty backdrop, by the way ^_^) in the hopes of giving focus to it and allowing me to use keyboard controls to select options, but while the cursor disappears (implying keyboard control), the game doesn't seem to respond to input. Perhaps it's freezing as soon as the game loads?
Then yes it goes into a freeze... In my standalone builds it goes straight into the game, but here, either it *is* loading, and I just can't see it, or it's gone into crash... Either way I've waited for EVER and didn't see it going into the game, so... I can't tell which it is!
(I don't know how to do a loader... Who knows how to do a loader in GMS? I Googled it and really, really can't find anything helpful)
Firstly lists and maps are the way to go when working with large amount of instances and or data and stats instead of array in GMS....see the help file in GM. List are really easy to save and load also in one shot as a variable and for building matrixes. Also in the help file which I always use when coding (since I'm self taught) is functions which directly solves your local collision question...I think it's something like collission_rectangle(); etc. and other shapes...but when you are in full control it's a lot more effort to avoid thinks going through walls and other solid objects, etc. This is handy for HTML5 cause its really a bitch coding HTML5 for performance is always a consideration...not to mention screen sizing and rotation.
Question though, I know collision_rectangle, collision_line, etc, but do they return more than one instance of collision? That was the crux of my question - let's say I have 10 objects and one explosion, and only 5 are in the explosion, if I want to test for objects caught in the explosion, do I have to initiate the test from each of the 10 objects, or is there a way of testing on the explosion and finding multiple overlaps?
And most of those older questions are out of the way, now I'm stuck on html 5 loading... Dunno if my game just doesn't load into html5 or if it's loading and I don't see it loading.
Any idea on how to do a loading screen between rooms? Google hasn't turned up anything I understand...
Alternatively, checking for collisions in the object (as you suggested) will work fine, but you'll probably end up doing unnecessary checks.
I'm trying to work out how to not do unnecesary checks but I haven't figured out how...
@dislekcia thanks, I'll look into html5 GMS issues!
Do you have a slowdown problem?
So yeah, I'll go on until there's actual performance issues :) thanks :)
Also, can you not just put all this code in a collision event instead?
Cos right now all my collisions are written into a script in each object's step, and it checks collision, but the question is detection multiple hits from one object.
And I'm gonn take @dislekcia's advice for now and not worry about optimization for the time being :)
Thanks :) I wonder if there's not a script way of doing that event, I pretty much dislike using more of those events than the bare basics of create, step and draw :P
I didn't actually know there was a collision event so I wrote everything into step events, and I'm reluctant to use more events because I thought keeping code contained and together would reduce messiness and make me less likely to be confused by my own code...
But yeah you're right, I'd put code into built-in engine stuff than try to figure out how to solve the same problems solved by people before me!
Thanks!
I'm so behind on this, gonna get cracking this week!
I just wish GM's interface was a bit easier to organise. Even dragging files and folders around can run into retarded situations.