mirror of
https://github.com/isometimes/rpi4-osdev
synced 2024-11-22 10:10:45 +00:00
Better collision detection in part6-breakout
This commit is contained in:
parent
05fc8b4733
commit
ba27d5ee26
2 changed files with 37 additions and 31 deletions
|
@ -85,8 +85,33 @@ i=8 : (i % zoom) = 0 -> advance the pointer
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
Perhaps you can see why we changed our loop to count from 1 rather than 0?
|
Perhaps you can see why we changed our outer loop to count from 1 rather than 0?
|
||||||
|
|
||||||
If you want, you can now make these changes to _fb.c_ in your part5-framebuffer code and exercise them properly in _kernel.c_ to check that they work. Don't forget to update the function definition in _fb.h_ to include the `zoom` parameter too.
|
If you want, you can now make these changes to _fb.c_ in your part5-framebuffer code and exercise them properly in _kernel.c_ to check that they work. Don't forget to update the function definition in _fb.h_ to include the `zoom` parameter too.
|
||||||
|
|
||||||
It is also now trivial to modify `drawString` to take a `zoom` parameter and pass it through, so I won't document the changes here.
|
It is also now trivial to modify `drawString` to take a `zoom` parameter and pass it through, so I won't document the changes here.
|
||||||
|
|
||||||
|
Object tracking
|
||||||
|
---------------
|
||||||
|
|
||||||
|
As we can now draw text (e.g. a score/lives counter), rectangles (paddle & bricks) and circles (ball), we can recreate the Breakout game screen. Check out `initBall()`, `initPaddle()`, `initBricks()` and `drawScoreboard(score, lives)` in our new _kernel.c_.
|
||||||
|
|
||||||
|
In addition to the graphics code, you'll see that we're keeping a record of each game object we create in the global `objects` array:
|
||||||
|
|
||||||
|
* its (x, y) coordinates
|
||||||
|
* its width & height
|
||||||
|
* what type of object it is (ball, paddle or brick)
|
||||||
|
* whether it's "alive"
|
||||||
|
|
||||||
|
We also store a global pointer to the ball and paddle object, so they're easy to track down!
|
||||||
|
|
||||||
|
As we'll need to knock out our bricks during gameplay, we create `removeObject(object)`, which simply draws a filled black rectangle over the object we pass, and sets its `alive` parameter to 0 to signal that it's now out of play.
|
||||||
|
|
||||||
|
To know that our ball is about to hit a brick (or indeed the paddle), we'll need to detect **collisions**. We simply conduct a search of the alive objects and return the first object we find whose coordinates overlap. If no object is found, we return 0. `detectCollision(object, xoff, yoff)` implements this. Note that `xoff` and `yoff` can be negative since the ball could be travelling in any direction.
|
||||||
|
|
||||||
|
Keyboard input
|
||||||
|
--------------
|
||||||
|
|
||||||
|
We'll be using the UART to take input, just like we did in part4-miniuart.
|
||||||
|
|
||||||
|
`getUart()` simply checks if a key has been pressed and, if so, it returns the character, otherwise 0. We don't want this function to wait for a key, because gameplay needs to continue regardless.
|
||||||
|
|
|
@ -53,42 +53,23 @@ void moveObject(struct Object *object, int xoff, int yoff)
|
||||||
object->y = object->y + yoff;
|
object->y = object->y + yoff;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Object *objectAt(unsigned int x, unsigned int y)
|
struct Object *detectCollision(struct Object *with, int xoff, int yoff)
|
||||||
{
|
{
|
||||||
for (int i=0; i<numobjs;i++) {
|
for (int i=0; i<numobjs;i++) {
|
||||||
if (x >= objects[i].x && x <= objects[i].x + objects[i].width) {
|
if (&objects[i] != with && objects[i].alive == 1) {
|
||||||
if (y >= objects[i].y && y <= objects[i].y + objects[i].height) {
|
if (with->x + xoff > objects[i].x + objects[i].width || objects[i].x > with->x + xoff + with->width) {
|
||||||
if (&objects[i] != ball && objects[i].alive == 1) {
|
// with is too far left or right to ocllide
|
||||||
return &objects[i];
|
} else if (with->y + yoff > objects[i].y + objects[i].height || objects[i].y > with->y + yoff + with->height) {
|
||||||
}
|
// with is too far up or down to ocllide
|
||||||
|
} else {
|
||||||
|
// Collision!
|
||||||
|
return &objects[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Object *detectCollision(int xoff, int yoff)
|
|
||||||
{
|
|
||||||
struct Object *collision;
|
|
||||||
|
|
||||||
unsigned int x = ball->x + xoff;
|
|
||||||
unsigned int y = ball->y + yoff;
|
|
||||||
|
|
||||||
collision = objectAt(x,y);
|
|
||||||
if (collision) return collision;
|
|
||||||
|
|
||||||
collision = objectAt(x + ball->width, y);
|
|
||||||
if (collision) return collision;
|
|
||||||
|
|
||||||
collision = objectAt(x, y + ball->height);
|
|
||||||
if (collision) return collision;
|
|
||||||
|
|
||||||
collision = objectAt(x + ball->width, y + ball->height);
|
|
||||||
if (collision) return collision;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// KEY HANDLER
|
// KEY HANDLER
|
||||||
|
|
||||||
unsigned char getUart()
|
unsigned char getUart()
|
||||||
|
@ -207,7 +188,7 @@ void main()
|
||||||
uart_loadOutputFifo();
|
uart_loadOutputFifo();
|
||||||
|
|
||||||
// Are we going to hit anything?
|
// Are we going to hit anything?
|
||||||
foundObject = detectCollision(velocity_x, velocity_y);
|
foundObject = detectCollision(ball, velocity_x, velocity_y);
|
||||||
|
|
||||||
if (foundObject) {
|
if (foundObject) {
|
||||||
if (foundObject == paddle) {
|
if (foundObject == paddle) {
|
||||||
|
|
Loading…
Reference in a new issue