mirror of
https://github.com/Rezmason/matrix.git
synced 2026-04-14 12:29:30 -07:00
Began work on the C port. To my knowledge, everything is working except the graphics code. The C API doesn't include bitmap compositing functions out-of-the-box.
This commit is contained in:
43
playdate/matrix_c/CMakeLists.txt
Normal file
43
playdate/matrix_c/CMakeLists.txt
Normal file
@@ -0,0 +1,43 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
|
||||
set(ENVSDK $ENV{PLAYDATE_SDK_PATH})
|
||||
|
||||
if (NOT ${ENVSDK} STREQUAL "")
|
||||
# Convert path from Windows
|
||||
file(TO_CMAKE_PATH ${ENVSDK} SDK)
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND bash -c "egrep '^\\s*SDKRoot' $HOME/.Playdate/config"
|
||||
COMMAND head -n 1
|
||||
COMMAND cut -c9-
|
||||
OUTPUT_VARIABLE SDK
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif()
|
||||
|
||||
if (NOT EXISTS ${SDK})
|
||||
message(FATAL_ERROR "SDK Path not found; set ENV value PLAYDATE_SDK_PATH")
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(CMAKE_CONFIGURATION_TYPES "Debug;Release")
|
||||
set(CMAKE_XCODE_GENERATE_SCHEME TRUE)
|
||||
|
||||
# Game Name Customization
|
||||
set(PLAYDATE_GAME_NAME ThePlaytrix)
|
||||
set(PLAYDATE_GAME_DEVICE ThePlaytrix_DEVICE)
|
||||
|
||||
project(${PLAYDATE_GAME_NAME} C ASM)
|
||||
|
||||
file(GLOB IMAGES
|
||||
"Source/images/*"
|
||||
)
|
||||
|
||||
if (TOOLCHAIN STREQUAL "armgcc")
|
||||
add_executable(${PLAYDATE_GAME_DEVICE} ${SDK}/C_API/buildsupport/setup.c main.c)
|
||||
else()
|
||||
add_library(${PLAYDATE_GAME_NAME} SHARED main.c ${IMAGES})
|
||||
endif()
|
||||
|
||||
include(${SDK}/C_API/buildsupport/playdate_game.cmake)
|
||||
BIN
playdate/matrix_c/Source/images/fade-gradient.png
Normal file
BIN
playdate/matrix_c/Source/images/fade-gradient.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.8 KiB |
BIN
playdate/matrix_c/Source/images/matrix-glyphs.png
Normal file
BIN
playdate/matrix_c/Source/images/matrix-glyphs.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
288
playdate/matrix_c/main.c
Normal file
288
playdate/matrix_c/main.c
Normal file
@@ -0,0 +1,288 @@
|
||||
//
|
||||
// main.c
|
||||
// Matrix Effect
|
||||
//
|
||||
// Created by Rezmason on 6/05/22.
|
||||
// Read the LICENSE file if you want to
|
||||
//
|
||||
|
||||
// #include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "pd_api.h"
|
||||
|
||||
typedef struct {
|
||||
int x;
|
||||
int y;
|
||||
int fadeIndex;
|
||||
int glyphIndex;
|
||||
float glyphCycle;
|
||||
float columnSpeedOffset;
|
||||
float columnTimeOffset;
|
||||
} Cell;
|
||||
|
||||
typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
int rowBytes;
|
||||
int hasMask;
|
||||
uint8_t *data;
|
||||
} BitmapView;
|
||||
|
||||
static PlaydateAPI* pd = NULL;
|
||||
|
||||
static const int glyphWidth = 20;
|
||||
static int numColumns;
|
||||
static int numRows;
|
||||
static int numCells;
|
||||
|
||||
static const int numGlyphs = 133;
|
||||
static const int numFades = 32;
|
||||
|
||||
static const float minSpeed = 0.15;
|
||||
static const float maxSpeed = 1;
|
||||
static float time = 0;
|
||||
static float speed = maxSpeed;
|
||||
|
||||
static float sineTable[360];
|
||||
static float wobbleA;
|
||||
static float wobbleB;
|
||||
|
||||
static LCDBitmap **glyphs = NULL;
|
||||
static Cell *cells = NULL;
|
||||
|
||||
static float randf() {
|
||||
return (float)rand() / (float)(RAND_MAX);
|
||||
}
|
||||
|
||||
static BitmapView* getBitmapView(LCDBitmap *bitmap)
|
||||
{
|
||||
BitmapView *bv = pd->system->realloc(NULL, sizeof(BitmapView));
|
||||
pd->graphics->getBitmapData(
|
||||
bitmap,
|
||||
&(bv->width),
|
||||
&(bv->height),
|
||||
&(bv->rowBytes),
|
||||
&(bv->hasMask),
|
||||
&(bv->data)
|
||||
);
|
||||
|
||||
return bv;
|
||||
}
|
||||
|
||||
static void freeBitmapView(BitmapView *bv)
|
||||
{
|
||||
pd->system->realloc(bv, 0);
|
||||
}
|
||||
|
||||
static void logBitmapViewToConsole(BitmapView *bv)
|
||||
{
|
||||
pd->system->logToConsole("bitmap: %i x %i %s", bv->width, bv->height, bv->hasMask ? "transparent" : "");
|
||||
|
||||
int dataSize = bv->rowBytes * bv->height;
|
||||
|
||||
{
|
||||
char line[bv->rowBytes * 8 + 1];
|
||||
for (int l = 0; l < bv->width; l++) {
|
||||
line[l] = (l % 8 == 0) ? '|' : '_';
|
||||
}
|
||||
for (int l = bv->width; l < bv->rowBytes * 8; l++) {
|
||||
line[l] = 'x';
|
||||
}
|
||||
line[bv->rowBytes * 8] = '\0';
|
||||
|
||||
pd->system->logToConsole("+%s+", line);
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (int y = 0; y < bv->height; y++) {
|
||||
|
||||
char line[bv->rowBytes * 8 + 1];
|
||||
for (int l = 0; l < bv->rowBytes * 8; l++) {
|
||||
line[l] = ' ';
|
||||
}
|
||||
line[bv->rowBytes * 8] = '\0';
|
||||
|
||||
int l = 0;
|
||||
for (int x = 0; x < bv->rowBytes; x++) {
|
||||
int byte = bv->data[i];
|
||||
int maskByte = bv->hasMask ? bv->data[i + dataSize] : 0xFF;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
int bit = (byte >> (7 - j)) & 1;
|
||||
int maskBit = (maskByte >> (7 - j)) & 1;
|
||||
if (maskBit) {
|
||||
line[l] = bit ? '#' : '.';
|
||||
} else {
|
||||
line[l] = bit ? '?' : ' ';
|
||||
}
|
||||
l++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
pd->system->logToConsole("[%s]", line);
|
||||
}
|
||||
}
|
||||
|
||||
static void init()
|
||||
{
|
||||
srand(pd->system->getSecondsSinceEpoch(NULL));
|
||||
|
||||
wobbleA = sqrt(2) / 50;
|
||||
wobbleB = sqrt(5) / 50;
|
||||
|
||||
int screenWidth = pd->display->getWidth();
|
||||
int screenHeight = pd->display->getHeight();
|
||||
numColumns = screenWidth / glyphWidth;
|
||||
numRows = screenHeight / glyphWidth;
|
||||
numCells = numColumns * numRows;
|
||||
|
||||
for (int i = 0; i < 360; i++)
|
||||
{
|
||||
sineTable[i] = sin(M_PI / 180 * i);
|
||||
}
|
||||
|
||||
const char *outErr = NULL;
|
||||
LCDBitmap *glyphSpritesheet = pd->graphics->loadBitmap("images/matrix-glyphs", &outErr);
|
||||
BitmapView *glyphSpritesheetBV = getBitmapView(glyphSpritesheet);
|
||||
|
||||
int spritesheetColumns = floor(glyphSpritesheetBV->width / glyphWidth);
|
||||
|
||||
LCDBitmap *fadeGradient = pd->graphics->loadBitmap("images/fade-gradient", &outErr);
|
||||
BitmapView *fadeGradientBV = getBitmapView(fadeGradient);
|
||||
|
||||
glyphs = pd->system->realloc(NULL, sizeof(LCDBitmap *) * numGlyphs * numFades);
|
||||
|
||||
LCDBitmap *glyph = pd->graphics->newBitmap(glyphWidth, glyphWidth, kColorBlack);
|
||||
|
||||
for (int i = 0; i < numGlyphs; i++) {
|
||||
int column = i % spritesheetColumns;
|
||||
int row = i / spritesheetColumns;
|
||||
/*
|
||||
pd->graphics.lockFocus(glyph)
|
||||
glyphSpritesheet:draw(-column * glyphWidth, -row * glyphWidth)
|
||||
pd->graphics.unlockFocus()
|
||||
glyphs[i] = {}
|
||||
for j = 1, numFades do
|
||||
local fade = (j - 1) / (numFades - 1)
|
||||
local variant = glyph:copy()
|
||||
glyphs[i][j] = variant
|
||||
pd->graphics.lockFocus(variant)
|
||||
fadeGradient:draw(fade * (glyphWidth - fadeGradient.width), 0)
|
||||
pd->graphics.unlockFocus()
|
||||
end
|
||||
*/
|
||||
}
|
||||
|
||||
pd->graphics->drawBitmap(glyphSpritesheet, 0, 20, kBitmapUnflipped);
|
||||
pd->graphics->drawBitmap(fadeGradient, 0, 0, kBitmapUnflipped);
|
||||
|
||||
pd->graphics->freeBitmap(glyphSpritesheet);
|
||||
freeBitmapView(glyphSpritesheetBV);
|
||||
pd->graphics->freeBitmap(fadeGradient);
|
||||
freeBitmapView(fadeGradientBV);
|
||||
|
||||
cells = pd->system->realloc(NULL, sizeof(Cell) * numCells);
|
||||
|
||||
int i = 0;
|
||||
for (int x = 0; x < numColumns; x++) {
|
||||
float columnTimeOffset = randf() * 1000;
|
||||
float columnSpeedOffset = random() * 0.5 + 0.5;
|
||||
for (int y = 0; y < numRows; y++) {
|
||||
Cell *cell = &cells[i];
|
||||
i++;
|
||||
|
||||
cell->x = x;
|
||||
cell->y = y;
|
||||
cell->glyphCycle = random();
|
||||
cell->columnTimeOffset = columnTimeOffset;
|
||||
cell->columnSpeedOffset = columnSpeedOffset;
|
||||
cell->glyphIndex = rand() % numGlyphs;
|
||||
cell->fadeIndex = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int update(void* ud)
|
||||
{
|
||||
float delta;
|
||||
if (pd->system->isCrankDocked()) {
|
||||
speed += 0.07;
|
||||
if (speed > maxSpeed) {
|
||||
speed = maxSpeed;
|
||||
}
|
||||
delta = pd->system->getElapsedTime() * speed;
|
||||
} else {
|
||||
speed -= 0.07;
|
||||
if (speed < minSpeed) {
|
||||
speed = minSpeed;
|
||||
}
|
||||
delta = pd->system->getElapsedTime() * speed + pd->system->getCrankChange() * 2 / 360;
|
||||
}
|
||||
pd->system->resetElapsedTime();
|
||||
time += delta;
|
||||
|
||||
for (int i = 0; i < numCells; i++) {
|
||||
int mustDraw = 0;
|
||||
Cell *cell = &cells[i];
|
||||
|
||||
float cellTime = cell->y * -0.03 + cell->columnTimeOffset + time * cell->columnSpeedOffset;
|
||||
float brightness = 4 * fmod(
|
||||
cellTime
|
||||
+ 0.3 * sineTable[(int)(fmod(wobbleA * cellTime, 360))]
|
||||
+ 0.2 * sineTable[(int)(fmod(wobbleB * cellTime, 360))],
|
||||
1
|
||||
);
|
||||
int fadeIndex = brightness * numFades;
|
||||
|
||||
if (fadeIndex < 1) fadeIndex = 1;
|
||||
if (fadeIndex > numFades) fadeIndex = numFades;
|
||||
if (cell->fadeIndex != fadeIndex) {
|
||||
cell->fadeIndex = fadeIndex;
|
||||
mustDraw = 1;
|
||||
}
|
||||
|
||||
cell->glyphCycle = cell->glyphCycle + delta * 2;
|
||||
if (cell->glyphCycle > 1) {
|
||||
cell->glyphCycle = fmod(cell->glyphCycle, 1);
|
||||
int glyphIndex = (cell->glyphIndex + (rand() % 20)) % numGlyphs;
|
||||
if (cell->glyphIndex != glyphIndex) {
|
||||
cell->glyphIndex = glyphIndex;
|
||||
if (fadeIndex < numFades) {
|
||||
mustDraw = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mustDraw) {
|
||||
/*
|
||||
pd->graphics->drawBitmap(
|
||||
glyphs[cell->glyphIndex * numFades + cell->fadeIndex],
|
||||
(cell->x - 1) * glyphWidth,
|
||||
(cell->y - 1) * glyphWidth,
|
||||
kBitmapUnflipped
|
||||
);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef _WINDLL
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int eventHandler(PlaydateAPI* playdate, PDSystemEvent event, uint32_t arg)
|
||||
{
|
||||
if ( event == kEventInit )
|
||||
{
|
||||
pd = playdate;
|
||||
pd->display->setRefreshRate(0);
|
||||
pd->system->setUpdateCallback(update, NULL);
|
||||
init();
|
||||
pd->system->resetElapsedTime();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
8
playdate/matrix_c/pdxinfo
Normal file
8
playdate/matrix_c/pdxinfo
Normal file
@@ -0,0 +1,8 @@
|
||||
name=The Playtrix
|
||||
author=Rezmason
|
||||
description=A familiar animation of mysterious raining symbols.
|
||||
bundleID=net.rezmason.theplaytrix
|
||||
version=1.0
|
||||
buildNumber=1
|
||||
imagePath=path/to/launcher/assets
|
||||
launchSoundPath=path/to/launch/sound/file
|
||||
Reference in New Issue
Block a user