Skip to content

Commit

Permalink
dont look at it
Browse files Browse the repository at this point in the history
- Adds scafffold for the first AWTRIX Game
- adds NewYear message
- adds FAQ Page
  • Loading branch information
Blueforcer committed Dec 28, 2023
1 parent d8f86a3 commit 4ee1061
Show file tree
Hide file tree
Showing 9 changed files with 312 additions and 13 deletions.
2 changes: 1 addition & 1 deletion docs/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
- [Quick start](quickstart.md)
- [Flasher](flasher.md)
- [Hardware](hardware.md)

- [FAQ](faq.md)
- Settings

- [Webinterface](webinterface.md)
Expand Down
14 changes: 14 additions & 0 deletions docs/faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Frequently Asked Questions (FAQ)

Welcome to the FAQ section. Here, you'll find answers to some of the most common questions i receive. If you don't find what you're looking for, please don't hesitate to join the [discord server](https://discord.gg/cyBCpdx).


### General Questions
#### Q: Can I Run AWTRIX Light Standalone?
A: No, AWTRIX is designed as a companion for your smart home system. It displays information based on what you send through its API.

#### Q: Can I Use Different Matrix Sizes Other Than 8x32?
A: Currently, AWTRIX is optimized for the Ulanzi Pixelclock, which supports a matrix size of 32x8 pixels. Other sizes are not supported at this time.

#### Q: Why Am I Getting an Error While Flashing My Ulanzi Clock with the AWTRIX Web Flasher?
A: If you encounter errors during the flashing process, i recommend trying a different USB cable and USB port. Some users have reported issues with the original cable provided with the device.
58 changes: 48 additions & 10 deletions src/DisplayManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <AwtrixFont.h>
#include <HTTPClient.h>
#include "base64.hpp"
#include "GameManager.h"

unsigned long lastArtnetStatusTime = 0;
const int numberOfChannels = 256 * 3;
Expand Down Expand Up @@ -621,7 +622,7 @@ bool DisplayManager_::generateCustomPage(const String &name, JsonObject doc, boo
{
String newIconName = doc["icon"].as<String>();

if (newIconName.length()>64)
if (newIconName.length() > 64)
{
customApp.jpegDataSize = decode_base64((const unsigned char *)newIconName.c_str(), customApp.jpegDataBuffer);
customApp.isGif = false;
Expand Down Expand Up @@ -901,7 +902,7 @@ bool DisplayManager_::generateNotification(uint8_t source, const char *json)
{
String iconValue = doc["icon"].as<String>();

if (iconValue.length()>64)
if (iconValue.length() > 64)
{
newNotification.jpegDataSize = decode_base64((const unsigned char *)iconValue.c_str(), newNotification.jpegDataBuffer);
newNotification.isGif = false;
Expand Down Expand Up @@ -1168,7 +1169,13 @@ bool universe2_complete = false;

void DisplayManager_::tick()
{
if (AP_MODE)
if (GAME_ACTIVE)
{
matrix->clear();
GameManager.tick();
matrix->show();
}
else if (AP_MODE)
{
HSVtext(2, 6, "AP MODE", true, 1);
}
Expand Down Expand Up @@ -1211,6 +1218,32 @@ void DisplayManager_::tick()
ARTNET_MODE = false;
}
}

DisplayManager.checkNewYear();
}

bool newYearEventTriggered = false;

void DisplayManager_::checkNewYear()
{
time_t now = time(nullptr);
struct tm *timeInfo;
timeInfo = localtime(&now);
if (timeInfo->tm_mon == 0 && timeInfo->tm_mday == 1 && timeInfo->tm_hour == 0 && timeInfo->tm_min == 0 && timeInfo->tm_sec == 0)
{
if (!newYearEventTriggered)
{
int year = 1900 + timeInfo->tm_year;
char message[300];
sprintf(message, "{'stack':false,'text':'%d','duration':20,'effect':'Fireworks','rtttl':'Auld:d=4,o=6,b=125:a5,d.,8d,d,f#,e.,8d,e,8f#,8e,d.,8d,f#,a,2b.,b,a.,8f#,f#,d,e.,8d,e,8f#,8e,d.,8b5,b5,a5,2d,16p'}", year);
DisplayManager.generateNotification(0, message);
newYearEventTriggered = true;
}
}
else
{
newYearEventTriggered = false;
}
}

void onDmxFrame(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t *data)
Expand Down Expand Up @@ -2003,13 +2036,13 @@ void DisplayManager_::setNewSettings(const char *json)
SHOW_TEMP = doc.containsKey("TEMP") ? doc["TEMP"].as<bool>() : SHOW_TEMP;
SHOW_BAT = doc.containsKey("BAT") ? doc["BAT"].as<bool>() : SHOW_BAT;

#ifndef ULANZI
if (doc.containsKey("VOL"))
{
DFP_VOLUME = doc["VOL"];
PeripheryManager.setVolume(DFP_VOLUME);
}
#endif
#ifndef ULANZI
if (doc.containsKey("VOL"))
{
DFP_VOLUME = doc["VOL"];
PeripheryManager.setVolume(DFP_VOLUME);
}
#endif

if (doc.containsKey("CCORRECTION"))
{
Expand Down Expand Up @@ -2476,6 +2509,11 @@ void DisplayManager_::drawRGBBitmap(int16_t x, int16_t y, uint32_t *bitmap, int1
}
}

void DisplayManager_::drawPixel(int16_t x0, int16_t y0, uint32_t color)
{
matrix->drawPixel(x0, y0, color);
}

void DisplayManager_::drawCircle(int16_t x0, int16_t y0, int16_t r, uint32_t color)
{
int16_t x = r;
Expand Down
2 changes: 2 additions & 0 deletions src/DisplayManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class DisplayManager_
void loadNativeApps();
void nextApp();
void previousApp();
void checkNewYear();
void leftButton();
void resetTextColor();
void clearMatrix();
Expand Down Expand Up @@ -85,6 +86,7 @@ class DisplayManager_
void drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color);
void drawFilledRect(int16_t x, int16_t y, int16_t w, int16_t h, uint32_t color);
void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint32_t color);
void drawPixel(int16_t x0, int16_t y0, uint32_t color);
void drawRGBBitmap(int16_t x, int16_t y, uint32_t *bitmap, int16_t w, int16_t h);
void drawCircle(int16_t x0, int16_t y0, int16_t r, uint32_t color);
void fillCircle(int16_t x0, int16_t y0, int16_t r, uint32_t color);
Expand Down
212 changes: 212 additions & 0 deletions src/GameManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
#include <GameManager.h>
#include "Globals.h"
#include "DisplayManager.h"

int mapWidth;
const int mapHeight = 8;
const float gravity = 0.1;
const float jumpSpeed = 2.0;
bool GameStarted = false;

enum Direction
{
LEFT,
RIGHT,
NONE
};

struct PlayerStats
{
int x, y;
bool isJumping;
float verticalSpeed;
uint32_t color;
PlayerStats() : x(0), y(0), isJumping(false), verticalSpeed(0), color(0xFFFFFF) {}
} GamePlayer;

// Globale Variablen für Spielzustand
Direction dir = NONE;
bool pressed = false;
bool jumpButtonPressed = false;

const char *levelMap[] = {
" ",
"# ",
"# O O O O O O O ",
"# P ",
"#### #### #### #### ####",
"# # # # # # # # # ",
"# #S #S ",
"GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG"};

// The getter for the instantiated singleton instance
GameManager_ &GameManager_::getInstance()
{
static GameManager_ instance;
return instance;
}

// Initialize the global shared instance
GameManager_ &GameManager = GameManager.getInstance();

void GameManager_::loadLevel()
{
mapWidth = strlen(levelMap[0]);
for (int y = 0; y < mapHeight; y++)
{
for (int x = 0; x < mapWidth; x++)
{
if (levelMap[y][x] == 'P')
{
GamePlayer.x = x;
GamePlayer.y = y;
return;
}
}
}
drawVisibleMapSection();
}

void GameManager_::tick()
{
if (!GameStarted)
loadLevel();
if (jumpButtonPressed)
{
jump();
}
applyGravityAndJump();
updatePlayerPosition();
drawVisibleMapSection();
drawPlayer();
}

void GameManager_::ControllerInput(String key, String status)
{
Serial.print(key);
Serial.print(":");
Serial.print(status);
Serial.println();
if (key == "LEFT")
{
dir = LEFT;
pressed = (status == "1");
}
else if (key == "RIGHT")
{
dir = RIGHT;
pressed = (status == "1");
}
else if (key == "JUMP")
{
jumpButtonPressed = (status == "1");
}
else
{
}
}

void GameManager_::updatePlayerPosition()
{
if (pressed)
{
switch (dir)
{
case LEFT:
GamePlayer.x = max(0, GamePlayer.x - 1);
break;
case RIGHT:
GamePlayer.x = min(mapWidth - 1, GamePlayer.x + 1);
break;
default:
break;
}
}
}

void GameManager_::applyGravityAndJump()
{
if (GamePlayer.isJumping)
{
GamePlayer.y += GamePlayer.verticalSpeed;
GamePlayer.verticalSpeed -= gravity;
if (GamePlayer.verticalSpeed < 0 && checkCollisionWithObjects(GamePlayer.x, GamePlayer.y))
{
GamePlayer.y = floor(GamePlayer.y);
GamePlayer.isJumping = false;
GamePlayer.verticalSpeed = 0;
}
}
}

void GameManager_::jump()
{
if (!GamePlayer.isJumping)
{
GamePlayer.isJumping = true;
GamePlayer.verticalSpeed = jumpSpeed;
}
}

bool GameManager_::checkCollisionWithObjects(int x, int y)
{

if (y >= mapHeight)
{
return false;
}

char mapChar = levelMap[y][x];
switch (mapChar)
{
case '#':
case '+':
return true;
default:
return false;
}
}

void GameManager_::drawVisibleMapSection()
{
int startColumn = max(0, GamePlayer.x - 16);
int endColumn = min(mapWidth, startColumn + 32);

for (int y = 0; y < mapHeight; y++)
{
for (int x = startColumn; x < endColumn; x++)
{
char mapChar = levelMap[y][x];
uint32_t objectColor = 0x0000;

switch (mapChar)
{
case 'G': // Boden
objectColor = 0xFF0000;
break;
case '#': // Block
objectColor = 0x00FF00;
break;
case 'O': // Münze
objectColor = 0xFFFF00;
break;
case 'S': // Spezielles Objekt
objectColor = 0x0000FF;
break;
case '+': // Zerbrechlicher Block
objectColor = 0xFF00FF;
break;
default:
objectColor = 0x000000;
break;
}
DisplayManager.drawPixel(x - startColumn, y, objectColor);
}
}
}

void GameManager_::drawPlayer()
{
int playerScreenX = GamePlayer.x - max(0, GamePlayer.x - 16);
DisplayManager.drawPixel(playerScreenX, GamePlayer.y, GamePlayer.color);
}
25 changes: 25 additions & 0 deletions src/GameManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef GameManager_h
#define GameManager_h

#include <Arduino.h>

class GameManager_
{
private:
GameManager_() = default;
public:
static GameManager_ &getInstance();
void setup();
void tick();
void loadLevel();
void updatePlayerPosition();
void drawVisibleMapSection();
void applyGravityAndJump();
bool checkCollisionWithObjects(int x, int y);
void drawPlayer();
void jump();
void ControllerInput(String key, String status);
};

extern GameManager_ &GameManager;
#endif
3 changes: 2 additions & 1 deletion src/Globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,4 +431,5 @@ String AUTH_PASS = "awtrix";
String BUTTON_CALLBACK = "";
bool SNOW = false;
float LDR_GAMMA = 3.0;
float LDR_FACTOR = 1.0;
float LDR_FACTOR = 1.0;
bool GAME_ACTIVE = false;
Loading

0 comments on commit 4ee1061

Please sign in to comment.