Need help fixing busted PACMAN code...

K12gamer

Member
I included a short (2 mb) open source file made with Gamemaker Studio 1.4
Link to open source Zip File: Drop Box or Google Drive

In it are two rooms...One where the game runs fine. But the other...I tried to speed up Pacman (and enemies) from speed 2 to speed 2.5.
(Note: I want to speed up Pacman + Enemies without changing the room speed)
When I increased the object movement speed Pacman started getting stuck on walls / unable to
make certain turns. Enemies seemed to stay in the middle of the screen.

Can someone possibly fix the code for speed 2.5 Pacman + Enemies and re-upload the demo?
I plan to offer this as a free resource to beginning GameMakers.

...
 
Last edited:

CloseRange

Member
your first problem is using drag and drop.....
but that's fine i suppose I just havn't used it in 10 years give or take.

Here is what I did.
all in the explorer_Bad:

right click collision with wall event and do change event. Set it to step event.

now in the actions drag on a move->Jump->move to contact
set direction to be "direction" (without quotes)

under control->other->start block and end block
surround all actions with those.

at the very top add control->variables->test variable
set variable to be "place_meeting(x+dx, y+dy, wall)" (if you want more info on place_meeting look in the game maker documentations, it's a special way of doing the collision event in the step event)
the value should be "true"

above the test variable drag on two set variables (it's to the left of the test variable)
the first one should be variable: dx
and value: lengthdir_x(speed, direction)

the second one should be variable: dy
and value: lengthdir_y(speed, direction)

again if you want info on lengthdir_x and y look in the docs, it's a trigonometry function and is good for things like this.
.
.
.
oh as for the enemy I never saw it getting stuck on walls once so I can't help ya there
 

TheouAegis

Member
You are going from an integral speed (2) to a fractional speed (2.5). So you are no longer aligning to the playing "grid", which your original code was probably focused on. So you just need to code things so it doesn't matter what speed you're actually going at as long as you have some way of aligning everything to that grid. Without looking at your code, since you're using D&D, I'd assume you have something along the lines of checking if there is no collision in the direction Pac-man wants to go. Well, let's assume each wall is 32x32p in size, in which case Pac-Man would be able to change direction every 32 pixels. Simply math shows 32/2=16, so at your old speed it would take Pac-Man 16 steps to traverse one wall-length. However, 32/2.5=12.8, which means after 12 steps Pac-Man won't have moved far enough (and will thus run into a wall) and after 13 steps he will have moved too far (and thus run into a wall). Thus, the only perfect solution is a speed of 1 or an integer easily divisible into the size of your walls. You could have speeds less than 1, just prevent Pac-man from actually moving at a fraction of a pixel -- or rather, don't let those fractions affect his fundamental mechanics. With speeds greater than 1, you need to make sure the speed is easily divisible into the size of your wall AND don't let fractional speeds affect fundamental movement. For example, a speed of 4/3 is divisible into 32 since 32/(4/3)=24, but because of floating point issues, if you include that "/3" in actual pixel positioning, then you will never be lined up with the grid properly, meaning even when it looks like Pac-Man's not blocked by any walls, there's a teensy-weensy fraction of a pixel actually blocked by a wall. But disregarding that nitpick for now, the easiest way to determine what speeds you can use is to write your desired speed out as a normal fraction, like 5/2 instead of 2.5; then look at the numerator. Is the numerator easily divisible into your wall width? If not, that's not a valid speed. Just at a glance, 2.5 seems like it should work with a 32x32 wall, but rewriting it, we see that 32 is clearly not easily divided by 5. This could take a while to sort through all the speeds, so just divide the size of your walls by 2 and use that as the numerator.

32 / 2 = 16
Any speed with 16 in the numerator should be valid. The baseline speed was 2 and 16/2=8, so any fraction with a denominator less than 8 should work. The closest values to 2.5 are 16/7 (2.285) and 16/6 (2.666), which can be reduced to 8/3. So with either of those speeds and proper handling of fractional coordinates, Pac-Man will be guaranteed to land on the 32x32 intervals.
 

K12gamer

Member
@CloseRange @TheouAegis thanks for the replies...I'll try to implement your ideas.
You're right...I'm not much of a coder...I got the original code from an old GM8 demo someone posted a long time ago...
then added drag and drop elements of my own. I re-skinned the graphics and added other effects to make a game.
The original game made things run faster just by varying the room speed. That worked well for me to...until I ported the game
to the Windows app store...and the varying room speeds made certain rooms run in slow motion.

Here's part of the original code in "Scripts" for the ghosts:

if (hspeed == 0)
{
if (random(3)<1 && place_free (x-32,y))
{
hspeed = -2;
vspeed = 0;


For Pacman each key press (up, down, left right) checks to see if position is collision free x or y is set at 4
 
Last edited:

curato

Member
I would think the place_fee should match the speed you are traveling. That is likely part of your collision issues. I would also say if you are going to use place_free I would use manual changing x and y to where you just figured out was free each frame. If you want to use hspeed and vspeed I would use the built in collision system to trigger an even to stop the motion when you bump into a wall object.
 

TheouAegis

Member
Yeah, I've seen some of the old Pacman GM8 games and wasn't a fan of their codes, even before I looked into how Pacman was made. lol

Ghosts only change direction at intersections, or every 8 pixels (the size of a tile) originally. There is no real collision detection in the ghosts ever, subsequently. Since Neither ghosts nor Pacman can move diagonally, you can tell if they are at an intersection using the conditional
if !((x + y) mod tile_size)
Replacing tile_size with the size of your tiles. Or if your tile size is a power of 2 (e.g.,2,4,8,16,32,64), you can also use
if !(x + y & tile_size)
The (x+y) part changes if your ghosts aren't aligned to the grid quite right. For example, the original code was if !(((x-4)+(y-4)) mod 8) because ghosts and Pacman were misaligned by 4 pixels.

Ghosts don't randomly change directions; they have very structured movement patterns. When the ghost reaches a junction (when x+y&7==0), it generates a list of all 4 directions around it. Another rule of ghosts is that they cannot reverse direction, so then the ghost removes the direction behind it from the list (i.e., if the ghost has direction 90, it removes 270 from the list). Then for each direction still in the list, it checks if there is a block in the way and removes that direction from the list if it is blocked. If there is only one direction left, the ghost heads in that direction; otherwise the ghost then picks a target location where it wants to go:
  • Blinky's target location is wherever Pacman is at that time.
    targetX = Pacman.x; targetY = Pacman.y;
    find_best_path();

  • Pinky's target location is 2 or 3 tiles ahead of Pacman.
    targetX = Pacman.x; targetY = Pacman.y;
    switch Pacman.direction {
    case 0: targetX += tile_size * 3; break;
    case 90: targetY -= tile_size * 3; break;
    case 180: targetX -= tile_size * 3; break;
    case 270: targetY += tile_size * 3; break;
    }
    find_best_path();
  • Inky's target location is to a pincer attack in tandem with Blinky.
    targetX = (Pacman.x * 2 - Blinky.x) mod room_width; //this was 256 in the old games
    targetY = (Pacman.y * 2 - Blinky.y) mod room_height; //again, this was 256
    find_best_path();
  • Clyde's target location was a bit more complex. If he was more than 4 tiles away from Pacman, the target location was Pacman's current position, but if he was closer than that, he would change direction; by default, he'd try to run down (I think it was down).
    if abs(Pacman.x - x) < tile_size * 4 && abs(Pacman.y - y) < tile_size * 4 {
    direction = 270;
    find_new_direction();
    }
    else {
    targetX = Pacman.x; targetY = Pacman.y;
    find_best_path();
    }
  • Fruit would try to get to the Ghost House, which obviously it can't get into, so it just moves around the field seemingly randomly.
The find_best_path() script would just be a script that would figure out which direction the target locations are relative to the ghost and then check if the best-fitting direction is in the list. If it is, it chooses that direction; but if it's not, it checks if the next best-fitting direction is in the list and chooses that. If even that's not available, it picks a random one from the list. This is the only random aspect of a ghost's movement, which usually only happens when the target location is behind the ghost.

The find_new_direction() script is also a random aspect, but it still follows the same direction picking rules as find_best_path().
 

TheouAegis

Member
and the varying room speeds made certain rooms run in slow motion.
Go into the global game settings and verify that you have "synchronization to avoid tearing" or whatever the option is labeled as unchecked. If it is unchecked, go ahead and put a checkmark next to it and then test your game on your computer again, not through the app store but as is. Then if slowdown happens there, then it means for whatever reason when the game is handled through the app store or whatever it automatically has v-sync enabled. That's the only thing I can think of that would cause slowdown like that. ... or you just forgot to reset the room speed at the start of every room. Lol

But yeah, modifying the room speed is not a good idea. Either set the room speed to 9999 and let the thing go crazy, or you set it to 60, which is standard, and find workable speeds.
 
@CloseRange @TheouAegis thanks for the replies...I'll try to implement your ideas.
You're right...I'm not much of a coder...I got the original code from an old GM8 demo someone posted a long time ago...
then added drag and drop elements of my own. I re-skinned the graphics and added other effects to make a game.
The original game made things run faster just by varying the room speed. That worked well for me to...until I ported the game
to the Windows app store...and the varying room speeds made certain rooms run in slow motion.

Here's part of the original code in "Scripts" for the ghosts:

if (hspeed == 0)
{
if (random(3)<1 && place_free (x-32,y))
{
hspeed = -2;
vspeed = 0;


For Pacman each key press (up, down, left right) checks to see if position is collision free x or y is set at 4
what code did you use to check the positions?
 
Top