Render magic gadgets (WIP)
This commit is contained in:
parent
e58e82b21b
commit
953f1d89ff
8
camera.c
8
camera.c
@ -15,7 +15,7 @@ System_Camera *camera_NewSystem(App *super) {
|
||||
|
||||
Box2 default_screen = {
|
||||
.lefttop = {.x = 0.0, .y = 0.0},
|
||||
.size = {.x = 1280, .y = 720}};
|
||||
.size = {.x = SCREEN_WIDTH, .y = SCREEN_HEIGHT}};
|
||||
sys->cam = sys->screen = default_screen;
|
||||
return sys;
|
||||
}
|
||||
@ -69,7 +69,7 @@ void camera_Advance(System_Camera *sys, Duration deltaTime) {
|
||||
}
|
||||
|
||||
|
||||
inline static Vec2 _camera_TransformSize(System_Camera *sys, Vec2 worldSize) {
|
||||
Vec2 camera_TransformSize(System_Camera *sys, Vec2 worldSize) {
|
||||
Vec2 result = {
|
||||
.x = worldSize.x / sys->cam.size.x * sys->screen.size.x,
|
||||
.y = worldSize.y / sys->cam.size.y * sys->screen.size.y};
|
||||
@ -78,11 +78,11 @@ inline static Vec2 _camera_TransformSize(System_Camera *sys, Vec2 worldSize) {
|
||||
|
||||
Vec2 camera_TransformVec2(System_Camera *sys, Vec2 world) {
|
||||
Vec2 relative = vec2_Minus(world, sys->cam.lefttop);
|
||||
return vec2_Add(sys->screen.lefttop, _camera_TransformSize(sys, relative));
|
||||
return vec2_Add(sys->screen.lefttop, camera_TransformSize(sys, relative));
|
||||
}
|
||||
Box2 camera_TransformBox2(System_Camera *sys, Box2 world) {
|
||||
Box2 result = {
|
||||
.lefttop = camera_TransformVec2(sys, world.lefttop),
|
||||
.size = _camera_TransformSize(sys, world.size)};
|
||||
.size = camera_TransformSize(sys, world.size)};
|
||||
return result;
|
||||
}
|
||||
|
5
camera.h
5
camera.h
@ -28,8 +28,9 @@ void camera_DeleteEntity(System_Camera *sys, uintptr_t id);
|
||||
|
||||
void camera_Advance(System_Camera *sys, Duration deltaTime);
|
||||
|
||||
Vec2 camera_TransformVec2(System_Camera *sys, Vec2 world);
|
||||
Box2 camera_TransformBox2(System_Camera *sys, Box2 world);
|
||||
Vec2 camera_TransformVec2(System_Camera *sys, Vec2 world); // Transform a Point, accounted for offset
|
||||
Box2 camera_TransformBox2(System_Camera *sys, Box2 world); // Transform a Rect, accounted for offset & zoom
|
||||
Vec2 camera_TransformSize(System_Camera *sys, Vec2 worldSize); // Transform a certain size, accounted for only zoom
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
2
main.cpp
2
main.cpp
@ -16,7 +16,7 @@ int main() {
|
||||
int frameCount = 0;
|
||||
|
||||
SetProcessDPIAware();
|
||||
HWND win = initgraph(1280, 720);
|
||||
HWND win = initgraph(SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
SetWindowTextA(win, "JacksEscape");
|
||||
|
||||
settextstyle(TEXTHEIGHT, 0, "Courier New");
|
||||
|
82
render_pattern.c
Normal file
82
render_pattern.c
Normal file
@ -0,0 +1,82 @@
|
||||
#include "render_pattern.h"
|
||||
#include <math.h>
|
||||
|
||||
|
||||
BYTE *render_DissolvePattern(double progress) {
|
||||
if (progress < .0)
|
||||
progress = .0;
|
||||
if (progress > 1.0)
|
||||
progress = 1.0;
|
||||
|
||||
int index = round(progress * 65);
|
||||
return (BYTE *)(render_DissolvePatternData + index * 8);
|
||||
}
|
||||
|
||||
|
||||
// generated from test_generate_pattern.cpp
|
||||
char render_DissolvePatternData[520] =
|
||||
"\xff\xff\xff\xff\xff\xff\xff\xff"
|
||||
"\x7f\xff\xff\xff\xff\xff\xff\xff"
|
||||
"\x3f\xff\xff\xff\xff\xff\xff\xff"
|
||||
"\x3f\xbf\xff\xff\xff\xff\xff\xff"
|
||||
"\x3f\x3f\xff\xff\xff\xff\xff\xff"
|
||||
"\x3f\x3f\x7f\xff\xff\xff\xff\xff"
|
||||
"\x3f\x3f\x3f\xff\xff\xff\xff\xff"
|
||||
"\x3f\x3f\x1f\xff\xff\xff\xff\xff"
|
||||
"\x3f\x1f\x1f\xff\xff\xff\xff\xff"
|
||||
"\x1f\x1f\x1f\xff\xff\xff\xff\xff"
|
||||
"\x0f\x1f\x1f\xff\xff\xff\xff\xff"
|
||||
"\x0f\x0f\x1f\xff\xff\xff\xff\xff"
|
||||
"\x0f\x0f\x0f\xff\xff\xff\xff\xff"
|
||||
"\x0f\x0f\x0f\xef\xff\xff\xff\xff"
|
||||
"\x0f\x0f\x0f\xcf\xff\xff\xff\xff"
|
||||
"\x0f\x0f\x0f\x8f\xff\xff\xff\xff"
|
||||
"\x0f\x0f\x0f\x0f\xff\xff\xff\xff"
|
||||
"\x0f\x0f\x0f\x0f\x7f\xff\xff\xff"
|
||||
"\x0f\x0f\x0f\x0f\x3f\xff\xff\xff"
|
||||
"\x0f\x0f\x0f\x0f\x1f\xff\xff\xff"
|
||||
"\x0f\x0f\x0f\x0f\x0f\xff\xff\xff"
|
||||
"\x0f\x0f\x0f\x0f\x07\xff\xff\xff"
|
||||
"\x0f\x0f\x0f\x07\x07\xff\xff\xff"
|
||||
"\x0f\x0f\x07\x07\x07\xff\xff\xff"
|
||||
"\x0f\x07\x07\x07\x07\xff\xff\xff"
|
||||
"\x07\x07\x07\x07\x07\xff\xff\xff"
|
||||
"\x03\x07\x07\x07\x07\xff\xff\xff"
|
||||
"\x03\x03\x07\x07\x07\xff\xff\xff"
|
||||
"\x03\x03\x03\x07\x07\xff\xff\xff"
|
||||
"\x03\x03\x03\x03\x07\xff\xff\xff"
|
||||
"\x03\x03\x03\x03\x03\xff\xff\xff"
|
||||
"\x03\x03\x03\x03\x03\xfb\xff\xff"
|
||||
"\x03\x03\x03\x03\x03\xf3\xff\xff"
|
||||
"\x03\x03\x03\x03\x03\xe3\xff\xff"
|
||||
"\x03\x03\x03\x03\x03\xc3\xff\xff"
|
||||
"\x03\x03\x03\x03\x03\x83\xff\xff"
|
||||
"\x03\x03\x03\x03\x03\x03\xff\xff"
|
||||
"\x03\x03\x03\x03\x03\x03\x7f\xff"
|
||||
"\x03\x03\x03\x03\x03\x03\x3f\xff"
|
||||
"\x03\x03\x03\x03\x03\x03\x1f\xff"
|
||||
"\x03\x03\x03\x03\x03\x03\x0f\xff"
|
||||
"\x03\x03\x03\x03\x03\x03\x07\xff"
|
||||
"\x03\x03\x03\x03\x03\x03\x03\xff"
|
||||
"\x03\x03\x03\x03\x03\x03\x01\xff"
|
||||
"\x03\x03\x03\x03\x03\x01\x01\xff"
|
||||
"\x03\x03\x03\x03\x01\x01\x01\xff"
|
||||
"\x03\x03\x03\x01\x01\x01\x01\xff"
|
||||
"\x03\x03\x01\x01\x01\x01\x01\xff"
|
||||
"\x03\x01\x01\x01\x01\x01\x01\xff"
|
||||
"\x01\x01\x01\x01\x01\x01\x01\xff"
|
||||
"\x00\x01\x01\x01\x01\x01\x01\xff"
|
||||
"\x00\x00\x01\x01\x01\x01\x01\xff"
|
||||
"\x00\x00\x00\x01\x01\x01\x01\xff"
|
||||
"\x00\x00\x00\x00\x01\x01\x01\xff"
|
||||
"\x00\x00\x00\x00\x00\x01\x01\xff"
|
||||
"\x00\x00\x00\x00\x00\x00\x01\xff"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\xff"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\xfe"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\xfc"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\xf8"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\xf0"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\xe0"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\xc0"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x80"
|
||||
"\x00\x00\x00\x00\x00\x00\x00"; // And the last \0 in the string terminator
|
10
render_pattern.h
Normal file
10
render_pattern.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
// for BYTE
|
||||
#include <minwindef.h>
|
||||
|
||||
// Returns a dissolve pattern for the given progress in [0,1]
|
||||
BYTE *render_DissolvePattern(double progress);
|
||||
|
||||
// The underlying data. 520 bytes
|
||||
extern char render_DissolvePatternData[520];
|
@ -1,9 +1,15 @@
|
||||
|
||||
#include "render_util.h"
|
||||
#include "camera.h"
|
||||
#include "render_pattern.h"
|
||||
#include "easyx.h"
|
||||
#include "types.h"
|
||||
#include "util/vector.h"
|
||||
#include "app.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <wingdi.h>
|
||||
|
||||
|
||||
extern "C" {
|
||||
@ -39,4 +45,65 @@ void render_DrawText(int x, int y, const char *str) {
|
||||
vector_Clear(tbuf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const FillMode render_DefaultMode = {
|
||||
.rop2 = R2_COPYPEN,
|
||||
.style = BS_SOLID,
|
||||
.hatch = 0,
|
||||
.rotate = {.microseconds = 0},
|
||||
.dissolve = {.microseconds = 0}};
|
||||
|
||||
|
||||
void render_SetModes(FillMode mode, TimePoint since) {
|
||||
if (mode.dissolve.microseconds != 0) {
|
||||
// Dissolve mode
|
||||
double progress = duration_Seconds(time_Since(since)) / duration_Seconds(mode.dissolve);
|
||||
setfillstyle(render_DissolvePattern(progress)); // progress is capped into [0,1] in this func
|
||||
setrop2(R2_COPYPEN);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode.rotate.microseconds != 0) {
|
||||
// Rotate mode
|
||||
int steps = round(duration_Seconds(time_Since(since)) / duration_Seconds(mode.dissolve));
|
||||
|
||||
static const long hatches[] = {HS_HORIZONTAL, HS_FDIAGONAL, HS_VERTICAL, HS_BDIAGONAL};
|
||||
setfillstyle(BS_HATCHED, hatches[steps % 4], NULL);
|
||||
setrop2(R2_COPYPEN);
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal mode
|
||||
setfillstyle(mode.style, mode.hatch, NULL);
|
||||
setrop2(mode.rop2);
|
||||
}
|
||||
|
||||
void render_FillScreen(FillMode mode, TimePoint since) {
|
||||
fillrectangle(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||
}
|
||||
|
||||
void render_FillRectW(App *app, Box2 rect, FillMode mode, TimePoint since) {
|
||||
if (app->camera)
|
||||
rect = camera_TransformBox2(app->camera, rect);
|
||||
else
|
||||
fprintf(stderr, "[WARN][render_FillRectW] called without an active camera system\n");
|
||||
fillrectangle(
|
||||
(int)round(rect.lefttop.x),
|
||||
(int)round(rect.lefttop.y),
|
||||
(int)round(rect.lefttop.x + rect.size.x),
|
||||
(int)round(rect.lefttop.y + rect.size.y));
|
||||
}
|
||||
|
||||
void render_FillCircleW(App *app, Vec2 center, double radius, FillMode mode, TimePoint since) {
|
||||
if (app->camera) {
|
||||
center = camera_TransformVec2(app->camera, center);
|
||||
radius = camera_TransformSize(app->camera, vec2(radius, 0)).x; // TODO non-aspect scaling
|
||||
} else
|
||||
fprintf(stderr, "[WARN][render_FillCircleW] called without an active camera system\n");
|
||||
fillcircle(
|
||||
(int)round(center.x),
|
||||
(int)round(center.y),
|
||||
(int)round(radius));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -15,6 +18,52 @@ extern "C" {
|
||||
void render_DrawText(int x, int y, const char *str);
|
||||
|
||||
|
||||
// Fill modes.
|
||||
typedef struct {
|
||||
// Most often it's:
|
||||
// R2_COPYPEN (Output = Pen color)
|
||||
// R2_BLACK (Output = Black)
|
||||
// R2_WHITE (Output = White)
|
||||
// R2_NOT (Output = NOT Screen color)
|
||||
//
|
||||
// https://docs.easyx.cn/zh-cn/setrop2
|
||||
int rop2;
|
||||
|
||||
// Style & hatch passed into setfillstyle()
|
||||
//
|
||||
// https://docs.easyx.cn/zh-cn/setfillstyle
|
||||
int style;
|
||||
long hatch;
|
||||
|
||||
// Rotates in /-\| every this amount of time, if not 0
|
||||
// Overrides style & hatch
|
||||
Duration rotate;
|
||||
|
||||
// Dissolve the entire screen in an animation in this
|
||||
// amount of time. Overrides rotate, style & hatch
|
||||
Duration dissolve;
|
||||
} FillMode;
|
||||
|
||||
// Default fill mode.
|
||||
// rop2 = R2_COPYPEN,
|
||||
// style = BS_SOLID,
|
||||
// others = 0
|
||||
extern const FillMode render_DefaultMode;
|
||||
|
||||
typedef struct _App App;
|
||||
|
||||
// Calls the required setfillstyle/setrop2 calls for the struct.
|
||||
void render_SetModes(FillMode mode, TimePoint since);
|
||||
|
||||
// Fills the entire screen
|
||||
void render_FillScreen(FillMode mode, TimePoint since);
|
||||
|
||||
// Fills a rectangle in world coordinates
|
||||
void render_FillRectW(App *app, Box2 rect, FillMode mode, TimePoint since);
|
||||
// Fills a circle in world coordinates
|
||||
void render_FillCircleW(App *app, Vec2 center, double radius, FillMode mode, TimePoint since);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
95
test_generate_patterns.cpp
Normal file
95
test_generate_patterns.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
// g++ test_generate_patterns.cpp -lsfml-graphics -lsfml-window -lsfml-system -lX11 -lGL
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
#include <SFML/Graphics.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace sf;
|
||||
|
||||
|
||||
uint8_t pattern[8];
|
||||
int x = 0, y = 0;
|
||||
|
||||
void outpattern() {
|
||||
cout << "\"";
|
||||
for (int i = 0; i < 8; i++)
|
||||
printf("\\x%02x", pattern[i]);
|
||||
cout << "\"" << endl;
|
||||
}
|
||||
|
||||
void setbit(int x, int y, bool value) {
|
||||
if (x < 0 || x > 7 || y < 0 || y > 7)
|
||||
return;
|
||||
uint8_t &target = pattern[y];
|
||||
if (value) { // set to 1
|
||||
uint8_t mask = 1 << (7 - x);
|
||||
target |= mask;
|
||||
} else { // set to 0
|
||||
uint8_t mask = ~(1 << (7 - x));
|
||||
target &= mask;
|
||||
}
|
||||
}
|
||||
|
||||
bool getbit(int x, int y) {
|
||||
if (x < 0 || x > 7 || y < 0 || y > 7)
|
||||
return false;
|
||||
uint8_t &target = pattern[y];
|
||||
uint8_t mask = 1 << (7 - x);
|
||||
return (target & mask) != 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
memset(pattern, -1, sizeof(pattern));
|
||||
|
||||
RenderWindow win(VideoMode(400, 400), "Generator");
|
||||
win.setVerticalSyncEnabled(true);
|
||||
win.setFramerateLimit(120);
|
||||
|
||||
outpattern();
|
||||
setbit(0, 0, false);
|
||||
outpattern();
|
||||
|
||||
|
||||
while (win.isOpen()) {
|
||||
Event e;
|
||||
while (win.pollEvent(e)) {
|
||||
if (e.type == Event::KeyPressed) {
|
||||
switch (e.key.code) {
|
||||
case Keyboard::Up:
|
||||
y--;
|
||||
break;
|
||||
case Keyboard::Down:
|
||||
y++;
|
||||
break;
|
||||
case Keyboard::Left:
|
||||
x--;
|
||||
break;
|
||||
case Keyboard::Right:
|
||||
x++;
|
||||
break;
|
||||
}
|
||||
setbit(x, y, false);
|
||||
outpattern();
|
||||
} else if (e.type == Event::Closed)
|
||||
win.close();
|
||||
}
|
||||
|
||||
win.clear();
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if (getbit(i, j)) {
|
||||
RectangleShape rect(Vector2f(50, 50));
|
||||
rect.setPosition(i * 50, j * 50);
|
||||
rect.setFillColor(Color::White);
|
||||
win.draw(rect);
|
||||
}
|
||||
}
|
||||
|
||||
win.display();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user