-
Notifications
You must be signed in to change notification settings - Fork 78
Add basic tetris to dev #69
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Changes from 4 commits
1929047
529a52e
5710243
ae0272e
b7d3670
8d85009
505e505
8d39d70
030bf0a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # Force format | ||
| $(info $(shell astyle --style=allman tetris.c ptetris.h)) | ||
|
|
||
| TOP_DIR=../.. | ||
| MODULE_NAME=tetris | ||
| MODULE_OBJS=tetris.o | ||
| include $(TOP_DIR)/modules/Makefile.modules | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| ML Tetris | ||
| ================== | ||
|
|
||
| Basic Tetris. Down/Left/Right to move. Up to rotate. | ||
| [Q] to quit. | ||
|
|
||
| :Authors: Daniel C | ||
| :License: GPL2 | ||
| :Summary: The Only Tetris for DSLRs. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,302 @@ | ||
| #ifndef PTETRIS_H | ||
| #define PTETRIS_H | ||
|
|
||
| #include <stdint.h> | ||
| #include <stdio.h> | ||
| #include <string.h> | ||
|
|
||
| void pt_pixel(int x, int y, int col); | ||
|
|
||
| extern uint32_t pt_colors[]; | ||
|
|
||
| // Max array size | ||
| #ifndef PT_MAX_WIDTH | ||
| #define PT_MAX_WIDTH 40 | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This file uses tabs, the .c uses 4-spaces. 4-spaces is preferred, please convert this file.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a copied directly from my ptetris project, which uses tabs. So I would have to convert the file to spaces every time I update the file. Not a big deal. |
||
| #define PT_MAX_HEIGHT 40 | ||
| #endif | ||
|
|
||
| // Darken the color around blocks | ||
| #ifndef PT_COL_DARKEN | ||
| #define PT_COL_DARKEN(x) x - (0x1b1b1b * 10) | ||
| #endif | ||
|
|
||
| // Basic random number generator | ||
| #ifndef PT_RAND | ||
| uint32_t pt_rand_x = 0x12345600; | ||
| int pt_rand(int max) { | ||
| pt_rand_x += 7; | ||
| pt_rand_x *= 0x87654321; | ||
| return pt_rand_x & max; | ||
| } | ||
|
|
||
| #define PT_RAND(x) pt_rand(x) | ||
| #endif | ||
|
|
||
| // Main runtime structure, tweak these in menu | ||
| struct PtRuntime { | ||
| int width; | ||
| int height; | ||
| int block_size; | ||
| int score; | ||
| }pt = { | ||
| 10, | ||
| 20, | ||
| 20, | ||
| 0, | ||
| }; | ||
|
|
||
| #define BLOCK_LEN 5 | ||
|
|
||
| // uint32_t pt_colors[BLOCK_LEN + 1] is expected to be defined | ||
|
|
||
| struct PtBlock { | ||
| int curr; | ||
| int x; | ||
| int y; | ||
| uint8_t b[][4][4]; | ||
| }pt_blocks = { | ||
| 0, 0, 0, | ||
| { | ||
| { | ||
| {0, 1, 0, 0}, | ||
| {0, 1, 0, 0}, | ||
| {0, 1, 0, 0}, | ||
| {0, 1, 0, 0}, | ||
| }, | ||
| { | ||
| {0, 0, 0, 0}, | ||
| {0, 2, 2, 2}, | ||
| {0, 0, 2, 0}, | ||
| {0, 0, 0, 0}, | ||
| }, | ||
| { | ||
| {0, 3, 0, 0}, | ||
| {0, 3, 0, 0}, | ||
| {0, 3, 3, 0}, | ||
| {0, 0, 0, 0}, | ||
| }, | ||
| { | ||
| {0, 0, 0, 0}, | ||
| {0, 4, 4, 0}, | ||
| {0, 4, 4, 0}, | ||
| {0, 0, 0, 0}, | ||
| }, | ||
| { | ||
| {0, 0, 0, 0}, | ||
| {0, 5, 5, 0}, | ||
| {5, 5, 0, 0}, | ||
| {0, 0, 0, 0}, | ||
| }, | ||
| { | ||
| {0, 0, 0, 0}, | ||
| {5, 5, 0, 0}, | ||
| {0, 5, 5, 0}, | ||
| {0, 0, 0, 0}, | ||
| }, | ||
| } | ||
| }; | ||
|
|
||
| struct PtField { | ||
| uint8_t b[PT_MAX_WIDTH][PT_MAX_HEIGHT]; | ||
| }; | ||
|
|
||
| struct PtField pt_main_field = {0}; | ||
|
|
||
| enum PtShift { | ||
| PT_NORMAL = 0, | ||
| PT_IMPOSSIBLE = 1, | ||
| PT_SIDE_SWIPE = 2, | ||
| PT_GAME_OVER = 3, | ||
| }; | ||
|
|
||
| enum PtButton { | ||
| PT_DOWN, | ||
| PT_LEFT, | ||
| PT_RIGHT, | ||
| PT_ROT, | ||
| PT_QUIT, | ||
| }; | ||
|
|
||
| void pt_reset() { | ||
| memset(&pt_main_field, 0, sizeof(struct PtField)); | ||
| pt_blocks.x = 0; | ||
| pt_blocks.y = 0; | ||
| pt_blocks.curr = 0; | ||
| pt.score = 0; | ||
| } | ||
|
|
||
| #ifndef PT_CUSTOM_DRAW_BLOCK | ||
| void pt_draw_block(int bx, int by, int col) { | ||
| bx *= pt.block_size; | ||
| by *= pt.block_size; | ||
|
|
||
| for (int x = 0; x < pt.block_size; x++) { | ||
| for (int y = 0; y < pt.block_size; y++) { | ||
| if (x == 0 || y == 0 || y == pt.block_size - 1 || x == pt.block_size - 1) { | ||
| pt_pixel(bx + x, by + y, PT_COL_DARKEN(pt_colors[col])); | ||
| } else { | ||
| pt_pixel(bx + x, by + y, pt_colors[col]); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| #endif | ||
|
|
||
| int pt_field_possible(uint8_t b[4][4], int ox, int oy) { | ||
| for (int x = 0; x < 4; x++) { | ||
| for (int y = 0; y < 4; y++) { | ||
| if ((x + ox) >= pt.width || x + ox <= -1) { | ||
| return 0; | ||
| } | ||
|
|
||
| // Detect impossible overlap | ||
| if (b[x + ox][y + oy] != 0 && | ||
| pt_main_field.b[x][y] != 0) { | ||
| return 0; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return 1; | ||
| } | ||
|
|
||
| int pt_field_rotate() { | ||
| uint8_t b[4][4]; | ||
|
|
||
| for (int x = 0; x < 4; x++) { | ||
| for (int y = 0; y < 4; y++) { | ||
| b[x][y] = pt_blocks.b[pt_blocks.curr][3 - y][x]; | ||
| } | ||
| } | ||
|
|
||
| if (!pt_field_possible(b, pt_blocks.x, pt_blocks.y)) { | ||
| return PT_IMPOSSIBLE; | ||
| } | ||
|
|
||
| for (int x = 0; x < 4; x++) { | ||
| for (int y = 0; y < 4; y++) { | ||
| pt_blocks.b[pt_blocks.curr][x][y] = b[x][y]; | ||
| } | ||
| } | ||
|
|
||
| return PT_NORMAL; | ||
| } | ||
|
|
||
| int pt_field_shift(int ox, int oy) { | ||
| for (int x = 0; x < 4; x++) { | ||
| for (int y = 0; y < 4; y++) { | ||
| if (pt_blocks.b[pt_blocks.curr][x][y] == 0) continue; | ||
|
|
||
| if (pt_blocks.b[pt_blocks.curr][x][y] != 0 && | ||
| pt_main_field.b[x + pt_blocks.x][y + pt_blocks.y] != 0) { | ||
| return PT_GAME_OVER; | ||
| } | ||
|
|
||
| // Detect gravity/hit | ||
| if (pt_main_field.b[x + pt_blocks.x][y + pt_blocks.y + oy] != 0 | ||
| || (y + pt_blocks.y + oy) >= pt.height) { | ||
| return PT_IMPOSSIBLE; | ||
| } | ||
|
|
||
| // Detect impossible side swipe | ||
| if (pt_main_field.b[pt_blocks.x + x + ox][pt_blocks.y + y + oy] != 0 | ||
| || (pt_blocks.x + x + ox) >= pt.width || (pt_blocks.x + x + ox) <= -1) { | ||
| pt_blocks.y += oy; | ||
| return PT_SIDE_SWIPE; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| pt_blocks.x += ox; | ||
| pt_blocks.y += oy; | ||
|
|
||
| return PT_NORMAL; | ||
| } | ||
|
|
||
| void pt_render() { | ||
| for (int x = 0; x < pt.width; x++) { | ||
| for (int y = 0; y < pt.height; y++) { | ||
| pt_draw_block(x, y, pt_main_field.b[x][y]); | ||
| } | ||
| } | ||
|
|
||
| for (int x = 0; x < 4; x++) { | ||
| for (int y = 0; y < 4; y++) { | ||
| if (pt_blocks.b[pt_blocks.curr][x][y] != 0) { | ||
| pt_draw_block(x + pt_blocks.x, y + pt_blocks.y, pt_blocks.b[pt_blocks.curr][x][y]); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| int pt_handle_input(int key) { | ||
| int r; | ||
| switch (key) { | ||
| case PT_DOWN: | ||
| while ((r = pt_field_shift(0, 1)) != PT_IMPOSSIBLE) { | ||
| if (r == PT_GAME_OVER) return r; | ||
| } | ||
| break; | ||
| case PT_LEFT: | ||
| return pt_field_shift(-1, 0); | ||
| case PT_RIGHT: | ||
| return pt_field_shift(1, 0); | ||
| case PT_ROT: | ||
| return pt_field_rotate(); | ||
| case PT_QUIT: | ||
| return PT_GAME_OVER; | ||
| } | ||
| return PT_NORMAL; | ||
| } | ||
|
|
||
| void pt_merge() { | ||
| for (int x = 0; x < 4; x++) { | ||
| for (int y = 0; y < 4; y++) { | ||
| if (pt_blocks.b[pt_blocks.curr][x][y] == 0) continue; | ||
| pt_main_field.b[x + pt_blocks.x][y + pt_blocks.y] | ||
| = pt_blocks.b[pt_blocks.curr][x][y]; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void pt_shift_down(int yo) { | ||
| for (int x = 0; x < pt.width; x++) { | ||
| for (int y = yo - 1; y != 0; y--) { | ||
| pt_main_field.b[x][y + 1] = pt_main_field.b[x][y]; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void pt_check_lines() { | ||
| for (int y = 0; y < pt.height; y++) { | ||
| int full = 0; | ||
| for (int x = 0; x < pt.width; x++) { | ||
| if (pt_main_field.b[x][y] != 0) { | ||
| full++; | ||
| } | ||
| } | ||
|
|
||
| if (full == pt.width) { | ||
| pt.score++; | ||
| pt_shift_down(y); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| int pt_step() { | ||
| // Operate gravity | ||
| switch (pt_field_shift(0, 1)) { | ||
| case PT_IMPOSSIBLE: | ||
| pt_merge(); | ||
| pt_blocks.curr = PT_RAND(BLOCK_LEN); | ||
| pt_blocks.y = 0; | ||
| break; | ||
| case PT_GAME_OVER: | ||
| return 1; | ||
| } | ||
|
|
||
| pt_check_lines(); | ||
| return 0; | ||
| } | ||
|
|
||
| #endif | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like it adds a dependency to the ML build system for "astyle", since all modules are built for all cams. I don't really want to do that. If you're volunteering to convert all ML code to be compatible, and then add an astyle dep, that's different! But it also feels like a separate task.
Probably remove this dep?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can comment it out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Annoyingly, there's an "official" coding style in doc/CODING_STYLE - which even suggests using astyle! But it is very clear this is not followed consistently.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice if the entire repo was formatted consistently, but that would be too big of a diff and mess with history+branches