Rotate portion of screen?

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

Rotate portion of screen?

A_Random_Person
This post was updated on .
I'm making a Pac-Man game that requires some portions of the screen being rotated/flipped. What is the best way I accomplish this? I cannot think of any ways.
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

ivant
Can you elaborate? What portions of the screen require this?

The only things I can think of are the pacman and the ghosts.
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

A_Random_Person
Yeah. Just that. Maybe method void rotateArea(int x1, int y1, int x2, int y2) or something.
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

WBahn
Administrator
So what is supposed to happen if I have some object, say fred, and I invoke

call fred.rotateArea(10,20,30,40);
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

A_Random_Person
I guess the area from (10, 20) to (30, 40) is rotated 90° clockwise, as long as the area is a square (in you example, it is).
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

WBahn
Administrator
Rotated about what point?

A huge fraction of trying to figure out how to solve a problem is being sure that the problem is clearly understood -- and that is often the hardest part.
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

WBahn
Administrator
In reply to this post by A_Random_Person
And what if the area is not square?

If you only want to rotate square areas, then your method should force that constraint by not allowing arbitrary coordinates to be passed to it.

What should happen if I invoke

call fred.rotateArea(10, 20, 30, 63);
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

A_Random_Person
This post was updated on .
The area is rotated around the center of the area, and if the area is not square fred.rotateArea(10, 20, 30, 63) will invoke Sys.error(whatever)
In pictures:

Turns into:
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

WBahn
Administrator
The next thing you need to consider is how you will handle squares that have odd length sides versus even length sides, given that you only have integers to work with.

I would recommend rotating it by 90 degrees about one of the corners and then shifting it back into position. You get to pick the corner. That part is actually very easy. But you have to consider what information you need to buffer since, as you draw the rotated pixels, you will be overwriting pixels that haven't been rotated yet.
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

ivant
When you program games you want to make them run fast. General rotation, even if it's just by 90/180/270 degrees, is going to be relatively slow on the HACK platform. Do you actually need it if the only thing that rotates is the pacman? Why not just have the 4 directional sprites precomputed and just use them?
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

A_Random_Person
Pac-Man has 3 animation frames, and each one will require 4 different sprites. That makes 3×4=12 different sprites. That will take way too long to make.
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

A_Random_Person
However, because I cannot think of any better way, I have done it ivant's way. It took a total of 9 sprites and now the PacMan class is 10 kilobytes. But again, there is no better way that I can think of that will not slow down the game (I will dread to think about how many lines of assembly code that will make 🤯).
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

ivant
A_Random_Person wrote
However, because I cannot think of any better way, I have done it ivant's way. It took a total of 9 sprites and now the <code>PacMan</code> class is 10 kilobytes.
Wow! How do you represent the sprites in the code?
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

A_Random_Person
I simply used the Sokoban Bitmap Editor and a few if's.
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

ivant
Please post the relevant Jack code.
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

A_Random_Person
method void draw(int frame, boolean color, int dir) {
var int memAddress;
let memAddress = 16384 + xPos + (yPos * 512);
if (color) {
if (frame = 0) {
do Memory.poke(memAddress+0, 992);
do Memory.poke(memAddress+32, 4088);
do Memory.poke(memAddress+64, 8188);
do Memory.poke(memAddress+96, 16382);
do Memory.poke(memAddress+128, 16382);
do Memory.poke(memAddress+160, 32767);
do Memory.poke(memAddress+192, 32767);
do Memory.poke(memAddress+224, 32767);
do Memory.poke(memAddress+256, 32767);
do Memory.poke(memAddress+288, 32767);
do Memory.poke(memAddress+320, 16382);
do Memory.poke(memAddress+352, 16382);
do Memory.poke(memAddress+384, 8188);
do Memory.poke(memAddress+416, 4088);
do Memory.poke(memAddress+448, 992);
do Memory.poke(memAddress+480, 0);
}
if (frame = 1) {
if (dir = 0) {
do Memory.poke(memAddress+0, 0);
do Memory.poke(memAddress+32, 3096);
do Memory.poke(memAddress+64, 7196);
do Memory.poke(memAddress+96, 15934);
do Memory.poke(memAddress+128, 15934);
do Memory.poke(memAddress+160, 32319);
do Memory.poke(memAddress+192, 32639);
do Memory.poke(memAddress+224, 32639);
do Memory.poke(memAddress+256, 32767);
do Memory.poke(memAddress+288, 32767);
do Memory.poke(memAddress+320, 16382);
do Memory.poke(memAddress+352, 16382);
do Memory.poke(memAddress+384, 8188);
do Memory.poke(memAddress+416, 4088);
do Memory.poke(memAddress+448, 992);
do Memory.poke(memAddress+480, 0);
}
if (dir = 1) {
do Memory.poke(memAddress+0, 0);
do Memory.poke(memAddress+32, 992);
do Memory.poke(memAddress+64, 4088);
do Memory.poke(memAddress+96, 8188);
do Memory.poke(memAddress+128, 16382);
do Memory.poke(memAddress+160, 16382);
do Memory.poke(memAddress+192, 32767);
do Memory.poke(memAddress+224, 32767);
do Memory.poke(memAddress+256, 32639);
do Memory.poke(memAddress+288, 32639);
do Memory.poke(memAddress+320, 32319);
do Memory.poke(memAddress+352, 15934);
do Memory.poke(memAddress+384, 15934);
do Memory.poke(memAddress+416, 7196);
do Memory.poke(memAddress+448, 3096);
do Memory.poke(memAddress+480, 0);
}
if (dir = 2) {
do Memory.poke(memAddress+0, 992);
do Memory.poke(memAddress+32, 4088);
do Memory.poke(memAddress+64, 8188);
do Memory.poke(memAddress+96, 16382);
do Memory.poke(memAddress+128, 16382);
do Memory.poke(memAddress+160, 32760);
do Memory.poke(memAddress+192, 32704);
do Memory.poke(memAddress+224, 32512);
do Memory.poke(memAddress+256, 32704);
do Memory.poke(memAddress+288, 32760);
do Memory.poke(memAddress+320, 16382);
do Memory.poke(memAddress+352, 16382);
do Memory.poke(memAddress+384, 8188);
do Memory.poke(memAddress+416, 4088);
do Memory.poke(memAddress+448, 992);
do Memory.poke(memAddress+480, 0);
}
if (dir = 3) {
do Memory.poke(memAddress+0, 1984);
do Memory.poke(memAddress+32, 8176);
do Memory.poke(memAddress+64, 16376);
do Memory.poke(memAddress+96, 32764);
do Memory.poke(memAddress+128, 32764);
do Memory.poke(memAddress+160, 8190);
do Memory.poke(memAddress+192, 1022);
do Memory.poke(memAddress+224, 254);
do Memory.poke(memAddress+256, 1022);
do Memory.poke(memAddress+288, 8190);
do Memory.poke(memAddress+320, 32764);
do Memory.poke(memAddress+352, 32764);
do Memory.poke(memAddress+384, 16376);
do Memory.poke(memAddress+416, 8176);
do Memory.poke(memAddress+448, 1984);
do Memory.poke(memAddress+480, 0);
}

}
if (frame = 2) {
if (dir = 0) {
do Memory.poke(memAddress+0, 0);
do Memory.poke(memAddress+32, 0);
do Memory.poke(memAddress+64, 0);
do Memory.poke(memAddress+96, 0);
do Memory.poke(memAddress+128, 0);
do Memory.poke(memAddress+160, 24579);
do Memory.poke(memAddress+192, 28679);
do Memory.poke(memAddress+224, 30735);
do Memory.poke(memAddress+256, 31775);
do Memory.poke(memAddress+288, 32319);
do Memory.poke(memAddress+320, 16254);
do Memory.poke(memAddress+352, 16382);
do Memory.poke(memAddress+384, 8188);
do Memory.poke(memAddress+416, 4088);
do Memory.poke(memAddress+448, 992);
do Memory.poke(memAddress+480, 0);
}
if (dir = 1) {
do Memory.poke(memAddress+0, 0);
do Memory.poke(memAddress+32, 992);
do Memory.poke(memAddress+64, 4088);
do Memory.poke(memAddress+96, 8188);
do Memory.poke(memAddress+128, 16382);
do Memory.poke(memAddress+160, 16254);
do Memory.poke(memAddress+192, 32319);
do Memory.poke(memAddress+224, 31775);
do Memory.poke(memAddress+256, 30735);
do Memory.poke(memAddress+288, 28679);
do Memory.poke(memAddress+320, 24579);
do Memory.poke(memAddress+352, 0);
do Memory.poke(memAddress+384, 0);
do Memory.poke(memAddress+416, 0);
do Memory.poke(memAddress+448, 0);
do Memory.poke(memAddress+480, 0);
}
if (dir = 2) {
do Memory.poke(memAddress+0, 992);
do Memory.poke(memAddress+32, 4064);
do Memory.poke(memAddress+64, 8128);
do Memory.poke(memAddress+96, 16256);
do Memory.poke(memAddress+128, 16128);
do Memory.poke(memAddress+160, 32256);
do Memory.poke(memAddress+192, 31744);
do Memory.poke(memAddress+224, 30720);
do Memory.poke(memAddress+256, 31744);
do Memory.poke(memAddress+288, 32256);
do Memory.poke(memAddress+320, 16128);
do Memory.poke(memAddress+352, 16256);
do Memory.poke(memAddress+384, 8128);
do Memory.poke(memAddress+416, 4064);
do Memory.poke(memAddress+448, 992);
do Memory.poke(memAddress+480, 0);
}
if (dir = 3) {
do Memory.poke(memAddress+0, 1984);
do Memory.poke(memAddress+32, 2032);
do Memory.poke(memAddress+64, 1016);
do Memory.poke(memAddress+96, 508);
do Memory.poke(memAddress+128, 252);
do Memory.poke(memAddress+160, 126);
do Memory.poke(memAddress+192, 62);
do Memory.poke(memAddress+224, 30);
do Memory.poke(memAddress+256, 62);
do Memory.poke(memAddress+288, 126);
do Memory.poke(memAddress+320, 252);
do Memory.poke(memAddress+352, 508);
do Memory.poke(memAddress+384, 1016);
do Memory.poke(memAddress+416, 2032);
do Memory.poke(memAddress+448, 1984);
do Memory.poke(memAddress+480, 0);
}
}
} else {
do Memory.poke(memAddress+0, 0);
do Memory.poke(memAddress+32, 0);
do Memory.poke(memAddress+64, 0);
do Memory.poke(memAddress+96, 0);
do Memory.poke(memAddress+128, 0);
do Memory.poke(memAddress+160, 0);
do Memory.poke(memAddress+192, 0);
do Memory.poke(memAddress+224, 0);
do Memory.poke(memAddress+256, 0);
do Memory.poke(memAddress+288, 0);
do Memory.poke(memAddress+320, 0);
do Memory.poke(memAddress+352, 0);
do Memory.poke(memAddress+384, 0);
do Memory.poke(memAddress+416, 0);
do Memory.poke(memAddress+448, 0);
}
return;
}
(Sorry about the absence of indentation. HTML didn't allow me to put in space characters at the start of a line. It's not my fault)
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

ivant
There is a principle in programming called Don't Repeat Yourself or DRY for short. It's not an absolute "commandment", but you should have a really good reason before you break it. In your code the line

do Memory.poke(addr, value);

is repeated about 160 times. Why not try using arrays and loops. You should be able to reduce the code size significantly.

If I get this correctly, your pacman is "jumping" from one position to the next, right? That is, it moves by 16 pixel steps. Is this how you want it to work?
Reply | Threaded
Open this post in threaded view
|

Re: Rotate portion of screen?

A_Random_Person
Yeah. If you see the video, you can see that it is smooth enough.
PacManRun.mp4