Discuss Scratch

cool_cartz427
New Scratcher
4 posts

Pac-Man game idea but no execution :(

Hi!

I'm quite a fan of Pac-Man and want to make a game like the original. However I looked at alot of tutorials on YouTube and their either too complicated, or the code they use is very faulty. I have though had some logical ideas of my own to create it myself. But of course, I'm a VERY big novice so I'm going to need some help.

Here's my first plan of action:

A deal that I've had while attempting to make this one game is how Pac moves. In the real game, when he's in a tunnel for example, he cant go up or down and keeps moving in the x axis. No tutorial really knows this and it kinda bugs tbh.
So I had the idea of Pac being on a trail that he cant ever get off from. Its sort of like a train on a railroad. Hopefully there is a way to make Pac-Man move in any desired direction but the requirements are that
1. He cant leave the path
2. He shall not face onto the walls that are to the sides of him if he's MOVING in the x or y axis.

I'm hoping this makes sense and that any of y'all can help me. Huge thanks!
DragonBeast829
Scratcher
100+ posts

Pac-Man game idea but no execution :(

If you store the map on a grid, you should be able to know which directions Pac-Man can move in based on what tiles are up, down, right, and left compared to Pac-Man's position.

If you don't know how to store a grid, I can help explain that too.
cool_cartz427
New Scratcher
4 posts

Pac-Man game idea but no execution :(

DragonBeast829 wrote:

If you store the map on a grid, you should be able to know which directions Pac-Man can move in based on what tiles are up, down, right, and left compared to Pac-Man's position.

If you don't know how to store a grid, I can help explain that too.
yeah that works well. I just hope the code can be simplified if that's possible. Those tutorials on YT did this and it didnt really make sense :[
also if its possible to use clones instead of the pen tool since that just adds more stuff which I don't really want. But if it's required, then ill roll with it
DragonBeast829
Scratcher
100+ posts

Pac-Man game idea but no execution :(

It's good that you want simplicity. Some people will tell you that sometimes things are just complicated, but a quote I really like is “An idiot admires complexity, a genius admires simplicity.”

You can probably simplify it any further, but in this case there's no need to. The Pac-Man board is inherently a grid of tiles, so there's no reason to store it as anything other than that: a grid of tiles.

You asked if you can use clones. Scratch has a limit of 300 clones, so you might hit that limit before you can draw everything you want.

I can explain the grid if you want, since you said it didn't make sense.

Last edited by DragonBeast829 (Yesterday 19:08:38)

cool_cartz427
New Scratcher
4 posts

Pac-Man game idea but no execution :(

DragonBeast829 wrote:

It's good that you want simplicity. Some people will tell you that sometimes things are just complicated, but a quote I really like is “An idiot admires complexity, a genius admires simplicity.”

You can probably simplify it any further, but in this case there's no need to. The Pac-Man board is inherently a grid of tiles, so there's no reason to store it as anything other than that: a grid of tiles.

You asked if you can use clones. Scratch has a limit of 300 clones, so you might hit that limit before you can draw everything you want.

I can explain the grid if you want, since you said it didn't make sense.
alr yea explain away. I'll get to work on the sprites since (I hate to brag) I am good at the art designing of stuff
DragonBeast829
Scratcher
100+ posts

Pac-Man game idea but no execution :(

A grid is a 2D collection of values, like this:
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
That's a 5x5 grid of zeros. We can draw something on it, like the Pac-Man maze that you want, or a smiley face:
0 1 0 1 0
0 1 0 1 0
0 0 0 0 0
1 0 0 0 1
0 1 1 1 0
I'm using 0 to represent a tile with nothing in it, and 1 to represent a tile that has something drawn on it. That's all fine and dandy but Scratch doesn't have built-in grids! This is what we can store in Scratch:
0 0 0 0 0 0 0 0 0 0 0 0 ... And so on
So, how can we represent a two-dimensional grid using just a one-dimensional list? Take another look at a 2D grid:
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
I've put a 1 at the first value of each row, to identify where the rows start. You won't actually need those markers in a real grid, but I've done it to help with explanations. Do you notice a pattern? Each row is the same length. In my case, 5. Now, let's flatten this to what Scratch expects, a single list of values.
1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0
Notice how you can still know when a new row starts. That's because the values are actually the exact same as the grid's, just represented in a way that Scratch can understand. With a bit of math, we can use this list as if it were the grid. So, to access a value on a grid, we need X (column) and Y (row) coordinates, right? But here, we only have a list index. How can we turn a Y value into the index the list expects? I'll explain the formula to access values on the grid, step by step. I'll use a dot to mark the cell corresponding to the list item we're accessing.

If we index the list based on only the X:
(item (x) of [grid v] :: list)
X=1
. 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
Then it appears to work, right? But only for the first row. We have to add 5 to get to the second row:
X=6
1 0 0 0 0
. 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
Let's look at if we index based on only the Y. To get the Y, we multiply the row number we want to access by the length of the rows.
(item ((y) * (row length)) of [grid v] :: list)
Y=2
1 0 0 0 0
1 0 0 0 0
. 0 0 0 0
1 0 0 0 0
1 0 0 0 0
But that's getting the third row, when we asked for the second! This is because multiplying 1 by 5 gives you 5. In our case, that should give you 0 because a Y of 1 is still the first row. To do this, we can subtract 1 from the Y we're trying to get, because multiplying 0 by 5 gives you 0.
(item (((y) - (1)) * (row length)) of [grid v] :: list)
Y=2
1 0 0 0 0
. 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
Look at that! We're getting the second row now. Now, just like the first time around, adding the X will let us get specific values within the row. But this time, we can also control the row we're reading from!
(item ((((y) - (1)) * (row length)) + (x)) of [grid v] :: list)
X=3
Y=3
1 0 0 0 0
1 0 0 0 0
1 0 . 0 0
1 0 0 0 0
1 0 0 0 0
Now we can read any value from the grid. Setting values uses the same formula to know which index to update. Just like with normal lists, be sure to populate the list with initial values before you try reading or setting.

We can also put this into a block to make it easier to use.
define get item x: (x) y: (y) on grid
set [grid value v] to (item ((((y) - (1)) * (row length)) + (x)) of [grid v] :: list)

If this is still confusing, let me know what parts of it you want clarification on. I wrote this right after waking up, so I may have explained some things strangely.
cool_cartz427
New Scratcher
4 posts

Pac-Man game idea but no execution :(

DragonBeast829 wrote:

A grid is a 2D collection of values, like this:
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
That's a 5x5 grid of zeros. We can draw something on it, like the Pac-Man maze that you want, or a smiley face:
0 1 0 1 0
0 1 0 1 0
0 0 0 0 0
1 0 0 0 1
0 1 1 1 0
I'm using 0 to represent a tile with nothing in it, and 1 to represent a tile that has something drawn on it. That's all fine and dandy but Scratch doesn't have built-in grids! This is what we can store in Scratch:
0 0 0 0 0 0 0 0 0 0 0 0 ... And so on
So, how can we represent a two-dimensional grid using just a one-dimensional list? Take another look at a 2D grid:
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
I've put a 1 at the first value of each row, to identify where the rows start. You won't actually need those markers in a real grid, but I've done it to help with explanations. Do you notice a pattern? Each row is the same length. In my case, 5. Now, let's flatten this to what Scratch expects, a single list of values.
1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0
Notice how you can still know when a new row starts. That's because the values are actually the exact same as the grid's, just represented in a way that Scratch can understand. With a bit of math, we can use this list as if it were the grid. So, to access a value on a grid, we need X (column) and Y (row) coordinates, right? But here, we only have a list index. How can we turn a Y value into the index the list expects? I'll explain the formula to access values on the grid, step by step. I'll use a dot to mark the cell corresponding to the list item we're accessing.

If we index the list based on only the X:
(item (x) of [grid v] :: list)
X=1
. 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
Then it appears to work, right? But only for the first row. We have to add 5 to get to the second row:
X=6
1 0 0 0 0
. 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
Let's look at if we index based on only the Y. To get the Y, we multiply the row number we want to access by the length of the rows.
(item ((y) * (row length)) of [grid v] :: list)
Y=2
1 0 0 0 0
1 0 0 0 0
. 0 0 0 0
1 0 0 0 0
1 0 0 0 0
But that's getting the third row, when we asked for the second! This is because multiplying 1 by 5 gives you 5. In our case, that should give you 0 because a Y of 1 is still the first row. To do this, we can subtract 1 from the Y we're trying to get, because multiplying 0 by 5 gives you 0.
(item (((y) - (1)) * (row length)) of [grid v] :: list)
Y=2
1 0 0 0 0
. 0 0 0 0
1 0 0 0 0
1 0 0 0 0
1 0 0 0 0
Look at that! We're getting the second row now. Now, just like the first time around, adding the X will let us get specific values within the row. But this time, we can also control the row we're reading from!
(item ((((y) - (1)) * (row length)) + (x)) of [grid v] :: list)
X=3
Y=3
1 0 0 0 0
1 0 0 0 0
1 0 . 0 0
1 0 0 0 0
1 0 0 0 0
Now we can read any value from the grid. Setting values uses the same formula to know which index to update. Just like with normal lists, be sure to populate the list with initial values before you try reading or setting.

We can also put this into a block to make it easier to use.
define get item x: (x) y: (y) on grid
set [grid value v] to (item ((((y) - (1)) * (row length)) + (x)) of [grid v] :: list)

If this is still confusing, let me know what parts of it you want clarification on. I wrote this right after waking up, so I may have explained some things strangely.
Okay I kind of understand the logic but I got a couple questions if that's ok


1. How is the Y (which is equal to one I believe) being multiplied by five make it end up in the third row?

2. If I'm not wrong, adding the X to the formula we did on Y is just so it can do the same thing as Y without making a new script I assume?

3. How come we changed the variable X and Y into the custom block ones?
DragonBeast829
Scratcher
100+ posts

Pac-Man game idea but no execution :(

cool_cartz427 wrote:

How is the Y (which is equal to one I believe) being multiplied by five make it end up in the third row?
The formula to find what row it's on is (y-1)*row_length. The -1 is there because otherwise we would be looking one row too far. Multiplying it by the row length (in my case, 5) then moves us by the number of rows equal to y. So, if Y = 1, we subtract 1 to get 0, and 0 * 5 is 0, meaning we're looking at row 1 and it relies entirely on the X (column). Y=3 on the other hand, subtract 1 to get Y=2, then 2*5 = 10. On a 5x5 grid, this is row 3, because the first row is items 1 through 5, second row is items 6 through 10, then the third is items 11 through 15. We want the Y axis (row) calculation to land on the last item of the last row from what we want, which is why it goes to 10 and not 11. This is because with adding the X (column), it moves over to the correct row and column (recall that Scratch stores lists in one dimension, so a “2D” grid is actually stored in a straight line). Hope that helps, lmk if you're still confused

cool_cartz427 wrote:

If I'm not wrong, adding the X to the formula we did on Y is just so it can do the same thing as Y without making a new script I assume?
The X moves in columns rather than rows. X and Y are both just numbers. What changes is how we process them. Y is semantically the row number, and X is the column. If it helps, we can start referring to them as row and column instead of X and Y.

cool_cartz427 wrote:

How come we changed the variable X and Y into the custom block ones?
So that we can call the custom block. X (column) and Y (row) are not the sprite's X and Y positions, they are the column and row of the item we want to read/set from the grid.

get item x: (2) y: (4) on grid
say (grid value) // Say the value of the retrieved item.

Last edited by DragonBeast829 (Today 15:54:36)

Powered by DjangoBB