mirror of
https://github.com/Kapendev/parin.git
synced 2025-05-03 00:19:55 +03:00
Almost done with spatial stuff.
This commit is contained in:
parent
dcb49d6cdd
commit
915b6f92a8
3 changed files with 79 additions and 47 deletions
|
@ -10,9 +10,9 @@
|
||||||
module parin.engine;
|
module parin.engine;
|
||||||
|
|
||||||
import rl = parin.rl;
|
import rl = parin.rl;
|
||||||
import stdc = joka.stdc;
|
|
||||||
import joka.ascii;
|
import joka.ascii;
|
||||||
import joka.io;
|
import joka.io;
|
||||||
|
import joka.memory;
|
||||||
public import joka.containers;
|
public import joka.containers;
|
||||||
public import joka.math;
|
public import joka.math;
|
||||||
public import joka.types;
|
public import joka.types;
|
||||||
|
@ -1257,8 +1257,8 @@ void openUrl(IStr url = "https://github.com/Kapendev/parin") {
|
||||||
@trusted
|
@trusted
|
||||||
void openWindow(int width, int height, const(IStr)[] args, IStr title = "Parin") {
|
void openWindow(int width, int height, const(IStr)[] args, IStr title = "Parin") {
|
||||||
if (rl.IsWindowReady) return;
|
if (rl.IsWindowReady) return;
|
||||||
engineState = cast(EngineState*) stdc.malloc(EngineState.sizeof);
|
engineState = cast(EngineState*) jokaMalloc(EngineState.sizeof);
|
||||||
stdc.memset(engineState, 0, EngineState.sizeof);
|
jokaMemset(engineState, 0, EngineState.sizeof);
|
||||||
// Raylib stuff.
|
// Raylib stuff.
|
||||||
rl.SetConfigFlags(rl.FLAG_WINDOW_RESIZABLE | rl.FLAG_VSYNC_HINT);
|
rl.SetConfigFlags(rl.FLAG_WINDOW_RESIZABLE | rl.FLAG_VSYNC_HINT);
|
||||||
rl.SetTraceLogLevel(rl.LOG_ERROR);
|
rl.SetTraceLogLevel(rl.LOG_ERROR);
|
||||||
|
@ -1411,7 +1411,7 @@ void closeWindow() {
|
||||||
engineState.loadTextBuffer.free();
|
engineState.loadTextBuffer.free();
|
||||||
engineState.saveTextBuffer.free();
|
engineState.saveTextBuffer.free();
|
||||||
engineState.assetsPath.free();
|
engineState.assetsPath.free();
|
||||||
stdc.free(engineState);
|
jokaFree(engineState);
|
||||||
engineState = null;
|
engineState = null;
|
||||||
rl.CloseAudioDevice();
|
rl.CloseAudioDevice();
|
||||||
rl.CloseWindow();
|
rl.CloseWindow();
|
||||||
|
@ -1918,34 +1918,28 @@ dchar dequeuePressedRune() {
|
||||||
/// Returns the directional input based on the WASD and arrow keys when they are down.
|
/// Returns the directional input based on the WASD and arrow keys when they are down.
|
||||||
/// The vector is not normalized.
|
/// The vector is not normalized.
|
||||||
Vec2 wasd() {
|
Vec2 wasd() {
|
||||||
auto result = Vec2();
|
with (Keyboard) return Vec2(
|
||||||
if (Keyboard.w.isDown || Keyboard.up.isDown) result.y -= 1.0f;
|
(d.isDown || right.isDown) - (a.isDown || left.isDown),
|
||||||
if (Keyboard.a.isDown || Keyboard.left.isDown) result.x -= 1.0f;
|
(s.isDown || down.isDown) - (w.isDown || up.isDown),
|
||||||
if (Keyboard.s.isDown || Keyboard.down.isDown) result.y += 1.0f;
|
);
|
||||||
if (Keyboard.d.isDown || Keyboard.right.isDown) result.x += 1.0f;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the directional input based on the WASD and arrow keys when they are pressed.
|
/// Returns the directional input based on the WASD and arrow keys when they are pressed.
|
||||||
/// The vector is not normalized.
|
/// The vector is not normalized.
|
||||||
Vec2 wasdPressed() {
|
Vec2 wasdPressed() {
|
||||||
auto result = Vec2();
|
with (Keyboard) return Vec2(
|
||||||
if (Keyboard.w.isPressed || Keyboard.up.isPressed) result.y -= 1.0f;
|
(d.isPressed || right.isPressed) - (a.isPressed || left.isPressed),
|
||||||
if (Keyboard.a.isPressed || Keyboard.left.isPressed) result.x -= 1.0f;
|
(s.isPressed || down.isPressed) - (w.isPressed || up.isPressed),
|
||||||
if (Keyboard.s.isPressed || Keyboard.down.isPressed) result.y += 1.0f;
|
);
|
||||||
if (Keyboard.d.isPressed || Keyboard.right.isPressed) result.x += 1.0f;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the directional input based on the WASD and arrow keys when they are released.
|
/// Returns the directional input based on the WASD and arrow keys when they are released.
|
||||||
/// The vector is not normalized.
|
/// The vector is not normalized.
|
||||||
Vec2 wasdReleased() {
|
Vec2 wasdReleased() {
|
||||||
auto result = Vec2();
|
with (Keyboard) return Vec2(
|
||||||
if (Keyboard.w.isReleased || Keyboard.up.isReleased) result.y -= 1.0f;
|
(d.isReleased || right.isReleased) - (a.isReleased || left.isReleased),
|
||||||
if (Keyboard.a.isReleased || Keyboard.left.isReleased) result.x -= 1.0f;
|
(s.isReleased || down.isReleased) - (w.isReleased || up.isReleased),
|
||||||
if (Keyboard.s.isReleased || Keyboard.down.isReleased) result.y += 1.0f;
|
);
|
||||||
if (Keyboard.d.isReleased || Keyboard.right.isReleased) result.x += 1.0f;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Plays the specified sound.
|
/// Plays the specified sound.
|
||||||
|
|
|
@ -155,12 +155,12 @@ struct BoxWorld {
|
||||||
foreach (i, ref properties; wallsProperties) {
|
foreach (i, ref properties; wallsProperties) {
|
||||||
auto id = cast(BaseBoxId) (i + 1);
|
auto id = cast(BaseBoxId) (i + 1);
|
||||||
auto point = getWallGridPoint(id);
|
auto point = getWallGridPoint(id);
|
||||||
grid[point.y, point.x].append(id & ~taggedBoxTagBit);
|
if (hasGridPoint(point)) grid[point.y, point.x].append(id & ~taggedBoxTagBit);
|
||||||
}
|
}
|
||||||
foreach (i, ref properties; actorsProperties) {
|
foreach (i, ref properties; actorsProperties) {
|
||||||
auto id = cast(BaseBoxId) (i + 1);
|
auto id = cast(BaseBoxId) (i + 1);
|
||||||
auto point = getActorGridPoint(id);
|
auto point = getActorGridPoint(id);
|
||||||
grid[point.y, point.x].append(id | taggedBoxTagBit);
|
if (hasGridPoint(point)) grid[point.y, point.x].append(id | taggedBoxTagBit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,6 +171,7 @@ struct BoxWorld {
|
||||||
}
|
}
|
||||||
|
|
||||||
IVec2 getGridPoint(IRect box) {
|
IVec2 getGridPoint(IRect box) {
|
||||||
|
if (!grid.length) assert(0, "Can't get a grid point from a disabled grid.");
|
||||||
return IVec2(
|
return IVec2(
|
||||||
box.position.x / gridTileWidth - (box.position.x < 0),
|
box.position.x / gridTileWidth - (box.position.x < 0),
|
||||||
box.position.y / gridTileHeight - (box.position.y < 0),
|
box.position.y / gridTileHeight - (box.position.y < 0),
|
||||||
|
@ -207,6 +208,10 @@ struct BoxWorld {
|
||||||
return getGridPoint(actors[id - 1]);
|
return getGridPoint(actors[id - 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasGridPoint(IVec2 point) {
|
||||||
|
return point.x >= 0 && point.y >= 0 && grid.has(point.y, point.x);
|
||||||
|
}
|
||||||
|
|
||||||
WallBoxId appendWall(IRect box, OneWaySide oneWaySide = OneWaySide.none) {
|
WallBoxId appendWall(IRect box, OneWaySide oneWaySide = OneWaySide.none) {
|
||||||
walls.append(box);
|
walls.append(box);
|
||||||
wallsProperties.append(WallBoxProperties());
|
wallsProperties.append(WallBoxProperties());
|
||||||
|
@ -214,8 +219,7 @@ struct BoxWorld {
|
||||||
auto id = cast(BaseBoxId) walls.length;
|
auto id = cast(BaseBoxId) walls.length;
|
||||||
if (grid.length) {
|
if (grid.length) {
|
||||||
auto point = getGridPoint(box);
|
auto point = getGridPoint(box);
|
||||||
if (box.position.x < 0 || box.position.y < 0 || !grid.has(point.y, point.x)) return id;
|
if (hasGridPoint(point)) grid[point.y, point.x].append(id & ~taggedBoxTagBit);
|
||||||
grid[point.y, point.x].append(id & ~taggedBoxTagBit);
|
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@ -227,65 +231,76 @@ struct BoxWorld {
|
||||||
auto id = cast(BaseBoxId) actors.length;
|
auto id = cast(BaseBoxId) actors.length;
|
||||||
if (grid.length) {
|
if (grid.length) {
|
||||||
auto point = getGridPoint(box);
|
auto point = getGridPoint(box);
|
||||||
if (box.position.x < 0 || box.position.y < 0 || !grid.has(point.y, point.x)) return id;
|
if (hasGridPoint(point)) grid[point.y, point.x].append(id | taggedBoxTagBit);
|
||||||
grid[point.y, point.x].append(id | taggedBoxTagBit);
|
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
WallBoxId[] getWallCollisions(IRect box) {
|
WallBoxId[] getWallCollisions(IRect box, bool canStopAtFirst = false) {
|
||||||
collisionIdsBuffer.clear();
|
collisionIdsBuffer.clear();
|
||||||
// TODO: Try not going over every neighboring cell please...
|
// TODO: Try not going over every neighboring cell please...
|
||||||
if (grid.length) {
|
if (grid.length) {
|
||||||
auto point = getGridPoint(box);
|
auto point = getGridPoint(box);
|
||||||
foreach (y; -1 .. 2) { foreach (x; -1 .. 2) {
|
foreach (y; -1 .. 2) { foreach (x; -1 .. 2) {
|
||||||
auto otherPoint = IVec2(point.x + x, point.y + y);
|
auto otherPoint = IVec2(point.x + x, point.y + y);
|
||||||
if (otherPoint.x < 0 || otherPoint.y < 0 || !grid.has(otherPoint.y, otherPoint.x)) continue;
|
if (!hasGridPoint(otherPoint)) continue;
|
||||||
foreach (taggedId; grid[point.y + y, point.x + x]) {
|
foreach (taggedId; grid[otherPoint.y, otherPoint.x]) {
|
||||||
auto i = (taggedId & ~taggedBoxTagBit) - 1;
|
auto i = (taggedId & ~taggedBoxTagBit) - 1;
|
||||||
auto isActor = taggedId & taggedBoxTagBit;
|
auto isActor = taggedId & taggedBoxTagBit;
|
||||||
if (isActor) continue;
|
if (isActor) continue;
|
||||||
if (walls[i].hasIntersection(box) && ~wallsProperties[i].flags & boxPassableFlag) collisionIdsBuffer.append(cast(BaseBoxId) (i + 1));
|
if (walls[i].hasIntersection(box) && ~wallsProperties[i].flags & boxPassableFlag) {
|
||||||
|
collisionIdsBuffer.append(cast(BaseBoxId) (i + 1));
|
||||||
|
if (canStopAtFirst) return collisionIdsBuffer[];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
} else {
|
} else {
|
||||||
foreach (i, wall; walls) {
|
foreach (i, wall; walls) {
|
||||||
if (wall.hasIntersection(box) && ~wallsProperties[i].flags & boxPassableFlag) collisionIdsBuffer.append(cast(BaseBoxId) (i + 1));
|
if (wall.hasIntersection(box) && ~wallsProperties[i].flags & boxPassableFlag) {
|
||||||
|
collisionIdsBuffer.append(cast(BaseBoxId) (i + 1));
|
||||||
|
if (canStopAtFirst) return collisionIdsBuffer[];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return collisionIdsBuffer[];
|
return collisionIdsBuffer[];
|
||||||
}
|
}
|
||||||
|
|
||||||
ActorBoxId[] getActorCollisions(IRect box) {
|
ActorBoxId[] getActorCollisions(IRect box, bool canStopAtFirst = false) {
|
||||||
collisionIdsBuffer.clear();
|
collisionIdsBuffer.clear();
|
||||||
// TODO: Try not going over every neighboring cell please...
|
// TODO: Try not going over every neighboring cell please...
|
||||||
if (grid.length) {
|
if (grid.length) {
|
||||||
auto point = getGridPoint(box);
|
auto point = getGridPoint(box);
|
||||||
foreach (y; -1 .. 2) { foreach (x; -1 .. 2) {
|
foreach (y; -1 .. 2) { foreach (x; -1 .. 2) {
|
||||||
auto otherPoint = IVec2(point.x + x, point.y + y);
|
auto otherPoint = IVec2(point.x + x, point.y + y);
|
||||||
if (otherPoint.x < 0 || otherPoint.y < 0 || !grid.has(otherPoint.y, otherPoint.x)) continue;
|
if (!hasGridPoint(otherPoint)) continue;
|
||||||
foreach (taggedId; grid[point.y + y, point.x + x]) {
|
foreach (taggedId; grid[otherPoint.y, otherPoint.x]) {
|
||||||
auto i = (taggedId & ~taggedBoxTagBit) - 1;
|
auto i = (taggedId & ~taggedBoxTagBit) - 1;
|
||||||
auto isWall = !(taggedId & taggedBoxTagBit);
|
auto isWall = !(taggedId & taggedBoxTagBit);
|
||||||
if (isWall) continue;
|
if (isWall) continue;
|
||||||
if (actors[i].hasIntersection(box) && ~actorsProperties[i].flags & boxPassableFlag) collisionIdsBuffer.append(cast(BaseBoxId) (i + 1));
|
if (actors[i].hasIntersection(box) && ~actorsProperties[i].flags & boxPassableFlag) {
|
||||||
|
collisionIdsBuffer.append(cast(BaseBoxId) (i + 1));
|
||||||
|
if (canStopAtFirst) return collisionIdsBuffer[];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
} else {
|
} else {
|
||||||
foreach (i, actor; actors) {
|
foreach (i, actor; actors) {
|
||||||
if (actor.hasIntersection(box) && ~actorsProperties[i].flags & boxPassableFlag) collisionIdsBuffer.append(cast(BaseBoxId) (i + 1));
|
if (actor.hasIntersection(box) && ~actorsProperties[i].flags & boxPassableFlag) {
|
||||||
|
collisionIdsBuffer.append(cast(BaseBoxId) (i + 1));
|
||||||
|
if (canStopAtFirst) return collisionIdsBuffer[];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return collisionIdsBuffer[];
|
return collisionIdsBuffer[];
|
||||||
}
|
}
|
||||||
|
|
||||||
WallBoxId hasWallCollision(IRect box) {
|
WallBoxId hasWallCollision(IRect box) {
|
||||||
auto boxes = getWallCollisions(box);
|
auto boxes = getWallCollisions(box, true);
|
||||||
return boxes.length ? boxes[0] : 0;
|
return boxes.length ? boxes[0] : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ActorBoxId hasActorCollision(IRect box) {
|
ActorBoxId hasActorCollision(IRect box) {
|
||||||
auto boxes = getActorCollisions(box);
|
auto boxes = getActorCollisions(box, true);
|
||||||
return boxes.length ? boxes[0] : 0;
|
return boxes.length ? boxes[0] : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,8 +338,31 @@ struct BoxWorld {
|
||||||
if (~properties.flags & boxPassableFlag && wallId) {
|
if (~properties.flags & boxPassableFlag && wallId) {
|
||||||
return wallId;
|
return wallId;
|
||||||
} else {
|
} else {
|
||||||
actor.position.x += moveSign;
|
if (grid.length) {
|
||||||
move -= moveSign;
|
auto oldPoint = getGridPoint(*actor);
|
||||||
|
actor.position.x += moveSign;
|
||||||
|
move -= moveSign;
|
||||||
|
auto newPoint = getGridPoint(*actor);
|
||||||
|
// TODO: Maybe think of how not to write this again. ...
|
||||||
|
if (oldPoint != newPoint) {
|
||||||
|
if (hasGridPoint(oldPoint)) {
|
||||||
|
foreach (j, taggedId; grid[oldPoint.y, oldPoint.x]) {
|
||||||
|
auto i = (taggedId & ~taggedBoxTagBit) - 1;
|
||||||
|
auto isActor = taggedId & taggedBoxTagBit;
|
||||||
|
if (isActor && (i + 1 == id)) {
|
||||||
|
grid[oldPoint.y, oldPoint.x].remove(j);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasGridPoint(newPoint)) {
|
||||||
|
grid[newPoint.y, newPoint.x].append(id | taggedBoxTagBit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
actor.position.x += moveSign;
|
||||||
|
move -= moveSign;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
module parin.ui;
|
module parin.ui;
|
||||||
|
|
||||||
import rl = parin.rl;
|
import rl = parin.rl;
|
||||||
import stdc = joka.stdc;
|
|
||||||
import joka.ascii;
|
import joka.ascii;
|
||||||
|
import joka.memory;
|
||||||
import parin.engine;
|
import parin.engine;
|
||||||
|
|
||||||
@safe @nogc nothrow:
|
@safe @nogc nothrow:
|
||||||
|
@ -112,10 +112,10 @@ int findSpaceInTextField(IStr text) {
|
||||||
void prepareUi() {
|
void prepareUi() {
|
||||||
if (uiState == null) {
|
if (uiState == null) {
|
||||||
// NOTE: This leaks. THIS IS SO BAD WHERE IS `Box::leak` IN THIS CODEBASE???
|
// NOTE: This leaks. THIS IS SO BAD WHERE IS `Box::leak` IN THIS CODEBASE???
|
||||||
uiState = cast(UiState*) stdc.malloc(UiState.sizeof);
|
uiState = cast(UiState*) jokaMalloc(UiState.sizeof);
|
||||||
uiPreviousState = cast(UiState*) stdc.malloc(UiState.sizeof);
|
uiPreviousState = cast(UiState*) jokaMalloc(UiState.sizeof);
|
||||||
stdc.memset(uiState, 0, UiState.sizeof);
|
jokaMemset(uiState, 0, UiState.sizeof);
|
||||||
stdc.memset(uiPreviousState, 0, UiState.sizeof);
|
jokaMemset(uiPreviousState, 0, UiState.sizeof);
|
||||||
// TODO: Should be changed to something better looking.
|
// TODO: Should be changed to something better looking.
|
||||||
uiState.mouseClickAction = Mouse.left;
|
uiState.mouseClickAction = Mouse.left;
|
||||||
uiState.keyboardClickAction = Keyboard.enter;
|
uiState.keyboardClickAction = Keyboard.enter;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue