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 = {
|
Box2 default_screen = {
|
||||||
.lefttop = {.x = 0.0, .y = 0.0},
|
.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;
|
sys->cam = sys->screen = default_screen;
|
||||||
return sys;
|
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 = {
|
Vec2 result = {
|
||||||
.x = worldSize.x / sys->cam.size.x * sys->screen.size.x,
|
.x = worldSize.x / sys->cam.size.x * sys->screen.size.x,
|
||||||
.y = worldSize.y / sys->cam.size.y * sys->screen.size.y};
|
.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 camera_TransformVec2(System_Camera *sys, Vec2 world) {
|
||||||
Vec2 relative = vec2_Minus(world, sys->cam.lefttop);
|
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 camera_TransformBox2(System_Camera *sys, Box2 world) {
|
||||||
Box2 result = {
|
Box2 result = {
|
||||||
.lefttop = camera_TransformVec2(sys, world.lefttop),
|
.lefttop = camera_TransformVec2(sys, world.lefttop),
|
||||||
.size = _camera_TransformSize(sys, world.size)};
|
.size = camera_TransformSize(sys, world.size)};
|
||||||
return result;
|
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);
|
void camera_Advance(System_Camera *sys, Duration deltaTime);
|
||||||
|
|
||||||
Vec2 camera_TransformVec2(System_Camera *sys, Vec2 world);
|
Vec2 camera_TransformVec2(System_Camera *sys, Vec2 world); // Transform a Point, accounted for offset
|
||||||
Box2 camera_TransformBox2(System_Camera *sys, Box2 world);
|
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
|
#ifdef __cplusplus
|
||||||
|
2
main.cpp
2
main.cpp
@ -16,7 +16,7 @@ int main() {
|
|||||||
int frameCount = 0;
|
int frameCount = 0;
|
||||||
|
|
||||||
SetProcessDPIAware();
|
SetProcessDPIAware();
|
||||||
HWND win = initgraph(1280, 720);
|
HWND win = initgraph(SCREEN_WIDTH, SCREEN_HEIGHT);
|
||||||
SetWindowTextA(win, "JacksEscape");
|
SetWindowTextA(win, "JacksEscape");
|
||||||
|
|
||||||
settextstyle(TEXTHEIGHT, 0, "Courier New");
|
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 "render_util.h"
|
||||||
|
#include "camera.h"
|
||||||
|
#include "render_pattern.h"
|
||||||
#include "easyx.h"
|
#include "easyx.h"
|
||||||
|
#include "types.h"
|
||||||
#include "util/vector.h"
|
#include "util/vector.h"
|
||||||
|
#include "app.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <wingdi.h>
|
||||||
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -39,4 +45,65 @@ void render_DrawText(int x, int y, const char *str) {
|
|||||||
vector_Clear(tbuf);
|
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
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -15,6 +18,52 @@ extern "C" {
|
|||||||
void render_DrawText(int x, int y, const char *str);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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