mirror of
https://github.com/Kapendev/parin.git
synced 2025-04-25 20:49:57 +03:00
More joka changes and map change and engineState is now a pointer.
This commit is contained in:
parent
cf8f71cfaa
commit
14ce68833c
4 changed files with 154 additions and 154 deletions
|
@ -10,18 +10,16 @@
|
|||
module parin.engine;
|
||||
|
||||
import rl = parin.rl;
|
||||
|
||||
import stdc = joka.stdc;
|
||||
import joka.ascii;
|
||||
import joka.io;
|
||||
import joka.unions;
|
||||
public import joka.containers;
|
||||
public import joka.faults;
|
||||
public import joka.math;
|
||||
public import joka.types;
|
||||
|
||||
@safe @nogc nothrow:
|
||||
|
||||
EngineState engineState;
|
||||
EngineState* engineState;
|
||||
|
||||
enum defaultEngineFontsCapacity = 64;
|
||||
enum defaultEngineResourcesCapacity = 256;
|
||||
|
@ -1272,6 +1270,7 @@ void openUrl(IStr url = "https://github.com/Kapendev/parin") {
|
|||
@trusted
|
||||
void openWindow(int width, int height, const(IStr)[] args, IStr title = "Parin") {
|
||||
if (rl.IsWindowReady) return;
|
||||
engineState = cast(EngineState*) stdc.malloc(EngineState.sizeof);
|
||||
engineState.envArgsBuffer.clear();
|
||||
foreach (arg; args) engineState.envArgsBuffer.append(arg);
|
||||
// Set raylib stuff.
|
||||
|
@ -1429,6 +1428,8 @@ void closeWindow() {
|
|||
engineState.loadTextBuffer.free();
|
||||
engineState.saveTextBuffer.free();
|
||||
engineState.assetsPath.free();
|
||||
stdc.free(engineState);
|
||||
engineState = null;
|
||||
}
|
||||
// This is outside because who knows, maybe raylib needs that.
|
||||
rl.CloseAudioDevice();
|
||||
|
|
|
@ -59,27 +59,26 @@ struct Tile {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Look at it again now with the Grid changes. It works, I know that :)
|
||||
// NOTE: Things like changing the grid row count might be interesting.
|
||||
struct TileMap {
|
||||
Grid!short data;
|
||||
Sz softMaxRowCount;
|
||||
Sz softMaxColCount;
|
||||
Sz softRowCount;
|
||||
Sz softColCount;
|
||||
int tileWidth = 16;
|
||||
int tileHeight = 16;
|
||||
Vec2 position;
|
||||
|
||||
enum maxRowCount = data.maxRowCount;
|
||||
enum maxColCount = data.maxColCount;
|
||||
enum maxCapacity = data.maxCapacity;
|
||||
|
||||
@safe @nogc nothrow:
|
||||
|
||||
this(int tileWidth, int tileHeight, Vec2 position = Vec2()) {
|
||||
this(Sz rowCount, Sz colCount, int tileWidth, int tileHeight) {
|
||||
this.tileWidth = tileWidth;
|
||||
this.tileHeight = tileHeight;
|
||||
this.softMaxRowCount = maxRowCount;
|
||||
this.softMaxColCount = maxColCount;
|
||||
this.position = position;
|
||||
this.data.fill(-1);
|
||||
resizeHard(rowCount, colCount);
|
||||
}
|
||||
|
||||
this(int tileWidth, int tileHeight) {
|
||||
this(defaultGridRowCount, defaultGridColCount, tileWidth, tileHeight);
|
||||
}
|
||||
|
||||
ref short opIndex(Sz row, Sz col) {
|
||||
|
@ -116,21 +115,7 @@ struct TileMap {
|
|||
}
|
||||
|
||||
Sz opDollar(Sz dim)() {
|
||||
static if (dim == 0) {
|
||||
return rowCount;
|
||||
} else static if (dim == 1) {
|
||||
return colCount;
|
||||
} else {
|
||||
assert(0, "WTF!");
|
||||
}
|
||||
}
|
||||
|
||||
Sz rowCount() {
|
||||
return data.length ? softMaxRowCount : 0;
|
||||
}
|
||||
|
||||
Sz colCount() {
|
||||
return data.length ? softMaxColCount : 0;
|
||||
return data.opDollar!dim();
|
||||
}
|
||||
|
||||
bool isEmpty() {
|
||||
|
@ -138,29 +123,50 @@ struct TileMap {
|
|||
}
|
||||
|
||||
bool has(Sz row, Sz col) {
|
||||
return row < rowCount && col < colCount;
|
||||
return row < softRowCount && col < softColCount;
|
||||
}
|
||||
|
||||
bool has(IVec2 position) {
|
||||
return has(position.y, position.x);
|
||||
}
|
||||
|
||||
@trusted
|
||||
Sz hardRowCount() {
|
||||
return data.rowCount;
|
||||
}
|
||||
|
||||
Sz hardColCount() {
|
||||
return data.colCount;
|
||||
}
|
||||
|
||||
void resizeHard(Sz newHardRowCount, Sz newHardColCount) {
|
||||
data.resizeBlank(newHardRowCount, newHardColCount);
|
||||
data.fill(-1);
|
||||
softRowCount = newHardRowCount;
|
||||
softColCount = newHardColCount;
|
||||
}
|
||||
|
||||
void resizeSoft(Sz newSoftRowCount, Sz newSoftColCount) {
|
||||
if (newSoftRowCount > hardRowCount || newSoftColCount > hardColCount) {
|
||||
assert(0, "Soft count must be smaller than hard count.");
|
||||
}
|
||||
softRowCount = newSoftRowCount;
|
||||
softColCount = newSoftColCount;
|
||||
}
|
||||
|
||||
void fill(short value) {
|
||||
data.fill(value);
|
||||
}
|
||||
|
||||
@trusted
|
||||
void free() {
|
||||
data.free();
|
||||
}
|
||||
|
||||
int width() {
|
||||
return cast(int) (colCount * tileWidth);
|
||||
return cast(int) (softColCount * tileWidth);
|
||||
}
|
||||
|
||||
int height() {
|
||||
return cast(int) (rowCount * tileHeight);
|
||||
return cast(int) (softRowCount * tileHeight);
|
||||
}
|
||||
|
||||
/// Returns the size of the tile map.
|
||||
|
@ -173,25 +179,27 @@ struct TileMap {
|
|||
return Vec2(tileWidth, tileHeight);
|
||||
}
|
||||
|
||||
Fault parse(IStr csv, int tileWidth, int tileHeight) {
|
||||
Fault parse(IStr csv, int newTileWidth, int newTileHeight) {
|
||||
if (csv.length == 0) return Fault.invalid;
|
||||
this.tileWidth = tileWidth;
|
||||
this.tileHeight = tileHeight;
|
||||
this.softMaxRowCount = 0;
|
||||
this.softMaxColCount = 0;
|
||||
this.data.fill(-1);
|
||||
if (data.isEmpty) {
|
||||
data.resizeBlank(defaultGridRowCount, defaultGridColCount);
|
||||
}
|
||||
tileWidth = newTileWidth;
|
||||
tileHeight = newTileHeight;
|
||||
softRowCount = 0;
|
||||
softColCount = 0;
|
||||
auto view = csv;
|
||||
while (view.length != 0) {
|
||||
softMaxRowCount += 1;
|
||||
softMaxColCount = 0;
|
||||
if (softMaxRowCount > maxRowCount) return Fault.invalid;
|
||||
softRowCount += 1;
|
||||
softColCount = 0;
|
||||
if (softRowCount > data.rowCount) return Fault.invalid;
|
||||
auto line = view.skipLine();
|
||||
while (line.length != 0) {
|
||||
softMaxColCount += 1;
|
||||
if (softMaxColCount > maxColCount) return Fault.invalid;
|
||||
softColCount += 1;
|
||||
if (softColCount > data.colCount) return Fault.invalid;
|
||||
auto tile = line.skipValue(',').toSigned();
|
||||
if (tile.isNone) return Fault.invalid;
|
||||
data[softMaxRowCount - 1, softMaxColCount - 1] = cast(short) tile.get();
|
||||
data[softRowCount - 1, softColCount - 1] = cast(short) tile.get();
|
||||
}
|
||||
}
|
||||
return Fault.none;
|
||||
|
@ -226,23 +234,23 @@ struct TileMap {
|
|||
}
|
||||
|
||||
IVec2 firstGridPosition(Vec2 topLeftWorldPosition, DrawOptions options = DrawOptions()) {
|
||||
if (rowCount == 0 || colCount == 0) return IVec2();
|
||||
if (softRowCount == 0 || softColCount == 0) return IVec2();
|
||||
auto result = IVec2();
|
||||
auto targetTileWidth = cast(int) (tileWidth * options.scale.x);
|
||||
auto targetTileHeight = cast(int) (tileHeight * options.scale.y);
|
||||
result.y = cast(int) floor(clamp((topLeftWorldPosition.y - position.y) / targetTileHeight, 0, rowCount - 1));
|
||||
result.x = cast(int) floor(clamp((topLeftWorldPosition.x - position.x) / targetTileWidth, 0, colCount - 1));
|
||||
result.y = cast(int) floor(clamp((topLeftWorldPosition.y - position.y) / targetTileHeight, 0, softRowCount - 1));
|
||||
result.x = cast(int) floor(clamp((topLeftWorldPosition.x - position.x) / targetTileWidth, 0, softColCount - 1));
|
||||
return result;
|
||||
}
|
||||
|
||||
IVec2 lastGridPosition(Vec2 bottomRightWorldPosition, DrawOptions options = DrawOptions()) {
|
||||
if (rowCount == 0 || colCount == 0) return IVec2();
|
||||
if (softRowCount == 0 || softColCount == 0) return IVec2();
|
||||
auto result = IVec2();
|
||||
auto targetTileWidth = cast(int) (tileWidth * options.scale.x);
|
||||
auto targetTileHeight = cast(int) (tileHeight * options.scale.y);
|
||||
auto extraTileCount = options.hook == Hook.topLeft ? 1 : 2;
|
||||
result.y = cast(int) floor(clamp((bottomRightWorldPosition.y - position.y) / targetTileHeight + extraTileCount, 0, rowCount - 1));
|
||||
result.x = cast(int) floor(clamp((bottomRightWorldPosition.x - position.x) / targetTileWidth + extraTileCount, 0, colCount - 1));
|
||||
result.y = cast(int) floor(clamp((bottomRightWorldPosition.y - position.y) / targetTileHeight + extraTileCount, 0, softRowCount - 1));
|
||||
result.x = cast(int) floor(clamp((bottomRightWorldPosition.x - position.x) / targetTileWidth + extraTileCount, 0, softColCount - 1));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -271,7 +279,7 @@ struct TileMap {
|
|||
}
|
||||
|
||||
auto result = Range(
|
||||
colCount,
|
||||
softColCount,
|
||||
firstGridPosition(topLeftWorldPosition, options),
|
||||
lastGridPosition(bottomRightWorldPosition, options),
|
||||
);
|
||||
|
@ -286,10 +294,10 @@ struct TileMap {
|
|||
|
||||
Fault saveTileMap(IStr path, TileMap map) {
|
||||
auto csv = prepareTempText();
|
||||
foreach (row; 0 .. map.rowCount) {
|
||||
foreach (col; 0 .. map.colCount) {
|
||||
foreach (row; 0 .. map.softRowCount) {
|
||||
foreach (col; 0 .. map.softColCount) {
|
||||
csv.append(map[row, col].toStr());
|
||||
if (col != map.colCount - 1) csv.append(',');
|
||||
if (col != map.softColCount - 1) csv.append(',');
|
||||
}
|
||||
csv.append('\n');
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
// ---
|
||||
|
||||
// TODO: Update all the doc comments here.
|
||||
// TODO: Add spatial partitioning after testing this in a game.
|
||||
// TODO: Add one-way collision support for moving walls.
|
||||
// NOTE: Maybe a world pixel size value could be useful.
|
||||
// TODO: Add spatial partitioning.
|
||||
// NOTE: Was working on spatial partitioning. The grid is done, just need to add values in it.
|
||||
|
||||
/// The `platformer` module provides a pixel-perfect physics engine.
|
||||
module parin.platformer;
|
||||
|
@ -21,10 +21,17 @@ import joka.types;
|
|||
|
||||
@safe @nogc nothrow:
|
||||
|
||||
alias BaseBoxId = int;
|
||||
alias ActorBoxId = BaseBoxId;
|
||||
alias WallBoxId = BaseBoxId;
|
||||
alias OneWaySide = RideSide;
|
||||
alias BaseBoxId = int;
|
||||
alias BaseBoxIdGroup = FixedList!(BaseBoxId, 510);
|
||||
|
||||
alias ActorBoxId = BaseBoxId;
|
||||
alias ActorBoxFlags = ubyte;
|
||||
alias WallBoxId = BaseBoxId;
|
||||
alias WallBoxFlags = ubyte;
|
||||
alias OneWaySide = RideSide;
|
||||
|
||||
enum boxPassableFlag = 0x1;
|
||||
enum boxRidingFlag = 0x2;
|
||||
|
||||
enum RideSide : ubyte {
|
||||
none,
|
||||
|
@ -111,86 +118,59 @@ struct BoxMover {
|
|||
}
|
||||
}
|
||||
|
||||
struct Box {
|
||||
IVec2 position;
|
||||
IVec2 size;
|
||||
|
||||
@safe @nogc nothrow:
|
||||
|
||||
pragma(inline, true)
|
||||
this(IVec2 position, IVec2 size) {
|
||||
this.position = position;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
pragma(inline, true)
|
||||
this(int x, int y, int w, int h) {
|
||||
this(IVec2(x, y), IVec2(w, h));
|
||||
}
|
||||
|
||||
pragma(inline, true)
|
||||
this(IVec2 position, int w, int h) {
|
||||
this(position, IVec2(w, h));
|
||||
}
|
||||
|
||||
pragma(inline, true)
|
||||
this(int x, int y, IVec2 size) {
|
||||
this(IVec2(x, y), size);
|
||||
}
|
||||
|
||||
pragma(inline, true)
|
||||
Rect toRect() {
|
||||
return Rect(position.toVec(), size.toVec());
|
||||
}
|
||||
|
||||
bool hasPoint(IVec2 point) {
|
||||
return (
|
||||
point.x > position.x &&
|
||||
point.x < position.x + size.x &&
|
||||
point.y > position.y &&
|
||||
point.y < position.y + size.y
|
||||
);
|
||||
}
|
||||
|
||||
bool hasIntersection(Box area) {
|
||||
return (
|
||||
position.x + size.x > area.position.x &&
|
||||
position.x < area.position.x + area.size.x &&
|
||||
position.y + size.y > area.position.y &&
|
||||
position.y < area.position.y + area.size.y
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns a string representation with a limited lifetime.
|
||||
IStr toStr() {
|
||||
return "({}, {}, {}, {})".format(position.x, position.y, size.x, size.y);
|
||||
}
|
||||
}
|
||||
|
||||
struct WallBoxProperties {
|
||||
Vec2 remainder;
|
||||
OneWaySide oneWaySide;
|
||||
bool isPassable;
|
||||
WallBoxFlags flags;
|
||||
byte gridX;
|
||||
byte gridY;
|
||||
}
|
||||
|
||||
struct ActorBoxProperties {
|
||||
Vec2 remainder;
|
||||
RideSide rideSide;
|
||||
bool isRiding;
|
||||
bool isPassable;
|
||||
ActorBoxFlags flags;
|
||||
byte gridX;
|
||||
byte gridY;
|
||||
}
|
||||
|
||||
struct BoxWorld {
|
||||
List!Box walls;
|
||||
List!Box actors;
|
||||
List!IRect walls;
|
||||
List!IRect actors;
|
||||
List!WallBoxProperties wallsProperties;
|
||||
List!ActorBoxProperties actorsProperties;
|
||||
List!ActorBoxId squishedIdsBuffer;
|
||||
List!BaseBoxId collisionIdsBuffer;
|
||||
Grid!BaseBoxIdGroup grid;
|
||||
int gridTileWidth;
|
||||
int gridTileHeight;
|
||||
|
||||
@safe @nogc nothrow:
|
||||
|
||||
ref Box getWall(WallBoxId id) {
|
||||
void enableSpatialGrid(Sz rowCount, Sz colCount, int tileWidth, int tileHeight) {
|
||||
gridTileWidth = tileWidth;
|
||||
gridTileHeight = tileHeight;
|
||||
foreach (i, ref properties; wallsProperties) {
|
||||
properties.gridX = walls[i].position.x / gridTileWidth - (walls[i].position.x < 0);
|
||||
properties.gridY = walls[i].position.y / gridTileHeight - (walls[i].position.y < 0);
|
||||
}
|
||||
foreach (i, ref properties; actorsProperties) {
|
||||
properties.gridX = actors[i].position.x / gridTileWidth - (actors[i].position.x < 0);
|
||||
properties.gridY = actors[i].position.y / gridTileHeight - (actors[i].position.y < 0);
|
||||
}
|
||||
grid.resizeBlank(rowCount, colCount);
|
||||
foreach (ref group; grid) {
|
||||
group.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void disableSpatialGrid() {
|
||||
gridTileWidth = 0;
|
||||
gridTileHeight = 0;
|
||||
grid.clear();
|
||||
}
|
||||
|
||||
ref IRect getWall(WallBoxId id) {
|
||||
if (id <= 0) {
|
||||
assert(0, "ID `0` is always invalid and represents a box that was never created.");
|
||||
} else if (id > walls.length) {
|
||||
|
@ -199,7 +179,7 @@ struct BoxWorld {
|
|||
return walls[id - 1];
|
||||
}
|
||||
|
||||
ref Box getActor(ActorBoxId id) {
|
||||
ref IRect getActor(ActorBoxId id) {
|
||||
if (id <= 0) {
|
||||
assert(0, "ID `0` is always invalid and represents a box that was never created.");
|
||||
} else if (id > actors.length) {
|
||||
|
@ -226,46 +206,54 @@ struct BoxWorld {
|
|||
return actorsProperties[id - 1];
|
||||
}
|
||||
|
||||
WallBoxId appendWall(Box box, OneWaySide oneWaySide = OneWaySide.none) {
|
||||
WallBoxId appendWall(IRect box, OneWaySide oneWaySide = OneWaySide.none) {
|
||||
walls.append(box);
|
||||
wallsProperties.append(WallBoxProperties());
|
||||
wallsProperties[$ - 1].oneWaySide = oneWaySide;
|
||||
if (gridTileWidth != 0 || gridTileHeight != 0) {
|
||||
wallsProperties[$ - 1].gridX = box.position.x / gridTileWidth - (box.position.x < 0);
|
||||
wallsProperties[$ - 1].gridY = box.position.y / gridTileHeight - (box.position.y < 0);
|
||||
}
|
||||
return cast(BaseBoxId) walls.length;
|
||||
}
|
||||
|
||||
ActorBoxId appendActor(Box box, RideSide rideSide = RideSide.none) {
|
||||
ActorBoxId appendActor(IRect box, RideSide rideSide = RideSide.none) {
|
||||
actors.append(box);
|
||||
actorsProperties.append(ActorBoxProperties());
|
||||
actorsProperties[$ - 1].rideSide = rideSide;
|
||||
if (gridTileWidth != 0 || gridTileHeight != 0) {
|
||||
actorsProperties[$ - 1].gridX = box.position.x / gridTileWidth - (box.position.x < 0);
|
||||
actorsProperties[$ - 1].gridY = box.position.y / gridTileHeight - (box.position.y < 0);
|
||||
}
|
||||
return cast(BaseBoxId) actors.length;
|
||||
}
|
||||
|
||||
WallBoxId hasWallCollision(Box box) {
|
||||
WallBoxId hasWallCollision(IRect box) {
|
||||
foreach (i, wall; walls) {
|
||||
if (wall.hasIntersection(box) && !wallsProperties[i].isPassable) return cast(BaseBoxId) (i + 1);
|
||||
if (wall.hasIntersection(box) && ~wallsProperties[i].flags & boxPassableFlag) return cast(BaseBoxId) (i + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ActorBoxId hasActorCollision(Box box) {
|
||||
ActorBoxId hasActorCollision(IRect box) {
|
||||
foreach (i, actor; actors) {
|
||||
if (actor.hasIntersection(box) && !actorsProperties[i].isPassable) return cast(BaseBoxId) (i + 1);
|
||||
if (actor.hasIntersection(box) && ~actorsProperties[i].flags & boxPassableFlag) return cast(BaseBoxId) (i + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
WallBoxId[] getWallCollisions(Box box) {
|
||||
WallBoxId[] getWallCollisions(IRect box) {
|
||||
collisionIdsBuffer.clear();
|
||||
foreach (i, wall; walls) {
|
||||
if (wall.hasIntersection(box) && !wallsProperties[i].isPassable) collisionIdsBuffer.append(cast(BaseBoxId) (i + 1));
|
||||
if (wall.hasIntersection(box) && ~wallsProperties[i].flags & boxPassableFlag) collisionIdsBuffer.append(cast(BaseBoxId) (i + 1));
|
||||
}
|
||||
return collisionIdsBuffer[];
|
||||
}
|
||||
|
||||
ActorBoxId[] getActorCollisions(Box box) {
|
||||
ActorBoxId[] getActorCollisions(IRect box) {
|
||||
collisionIdsBuffer.clear();
|
||||
foreach (i, actor; actors) {
|
||||
if (actor.hasIntersection(box) && !actorsProperties[i].isPassable) collisionIdsBuffer.append(cast(BaseBoxId) (i + 1));
|
||||
if (actor.hasIntersection(box) && ~actorsProperties[i].flags & boxPassableFlag) collisionIdsBuffer.append(cast(BaseBoxId) (i + 1));
|
||||
}
|
||||
return collisionIdsBuffer[];
|
||||
}
|
||||
|
@ -281,7 +269,7 @@ struct BoxWorld {
|
|||
int moveSign = move.sign();
|
||||
properties.remainder.x -= move;
|
||||
while (move != 0) {
|
||||
auto tempBox = Box(actor.position + IVec2(moveSign, 0), actor.size);
|
||||
auto tempBox = IRect(actor.position + IVec2(moveSign, 0), actor.size);
|
||||
auto wallId = hasWallCollision(tempBox);
|
||||
if (wallId) {
|
||||
// One way stuff.
|
||||
|
@ -302,11 +290,12 @@ struct BoxWorld {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!properties.isPassable && wallId) {
|
||||
if (~properties.flags & boxPassableFlag && wallId) {
|
||||
return wallId;
|
||||
} else {
|
||||
actor.position.x += moveSign;
|
||||
move -= moveSign;
|
||||
properties.gridX = actor.position.x / gridTileWidth - (actor.position.x < 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -335,7 +324,7 @@ struct BoxWorld {
|
|||
int moveSign = move.sign();
|
||||
properties.remainder.y -= move;
|
||||
while (move != 0) {
|
||||
auto tempBox = Box(actor.position + IVec2(0, moveSign), actor.size);
|
||||
auto tempBox = IRect(actor.position + IVec2(0, moveSign), actor.size);
|
||||
auto wallId = hasWallCollision(tempBox);
|
||||
if (wallId) {
|
||||
// One way stuff.
|
||||
|
@ -356,11 +345,12 @@ struct BoxWorld {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!properties.isPassable && wallId) {
|
||||
if (~properties.flags & boxPassableFlag && wallId) {
|
||||
return wallId;
|
||||
} else {
|
||||
actor.position.y += moveSign;
|
||||
move -= moveSign;
|
||||
properties.gridY = actor.position.y / gridTileHeight - (actor.position.y < 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -443,8 +433,8 @@ struct BoxWorld {
|
|||
auto move = properties.remainder.round().toIVec();
|
||||
if (move.x != 0 || move.y != 0) {
|
||||
foreach (i, ref actorProperties; actorsProperties) {
|
||||
actorProperties.isRiding = false;
|
||||
if (!actorProperties.rideSide || actorProperties.isPassable) continue;
|
||||
actorProperties.flags &= ~boxRidingFlag;
|
||||
if (!actorProperties.rideSide || actorProperties.flags & boxPassableFlag) continue;
|
||||
auto rideBox = actors[i];
|
||||
final switch (actorProperties.rideSide) with (RideSide) {
|
||||
case none: break;
|
||||
|
@ -453,16 +443,17 @@ struct BoxWorld {
|
|||
case right: rideBox.position.x -= 1; break;
|
||||
case bottom: rideBox.position.y -= 1; break;
|
||||
}
|
||||
actorProperties.isRiding = wall.hasIntersection(rideBox);
|
||||
actorProperties.flags |= wall.hasIntersection(rideBox) ? boxRidingFlag : 0x0;
|
||||
}
|
||||
}
|
||||
if (move.x != 0) {
|
||||
wall.position.x += move.x;
|
||||
properties.remainder.x -= move.x;
|
||||
if (!properties.isPassable) {
|
||||
properties.isPassable = true;
|
||||
properties.gridX = wall.position.x / gridTileWidth - (wall.position.x < 0);
|
||||
if (~properties.flags & boxPassableFlag) {
|
||||
properties.flags |= boxPassableFlag;
|
||||
foreach (i, ref actor; actors) {
|
||||
if (actorsProperties[i].isPassable) continue;
|
||||
if (actorsProperties[i].flags & boxPassableFlag) continue;
|
||||
if (wall.hasIntersection(actor)) {
|
||||
// Push actor.
|
||||
auto wallLeft = wall.position.x;
|
||||
|
@ -474,21 +465,22 @@ struct BoxWorld {
|
|||
// Squish actor.
|
||||
squishedIdsBuffer.append(cast(BaseBoxId) (i + 1));
|
||||
}
|
||||
} else if (actorsProperties[i].isRiding) {
|
||||
} else if (actorsProperties[i].flags & boxRidingFlag) {
|
||||
// Carry actor.
|
||||
moveActorX(cast(BaseBoxId) (i + 1), move.x);
|
||||
}
|
||||
}
|
||||
properties.isPassable = false;
|
||||
properties.flags &= ~boxPassableFlag;
|
||||
}
|
||||
}
|
||||
if (move.y != 0) {
|
||||
wall.position.y += move.y;
|
||||
properties.remainder.y -= move.y;
|
||||
if (!properties.isPassable) {
|
||||
properties.isPassable = true;
|
||||
properties.gridY = wall.position.y / gridTileHeight - (wall.position.y < 0);
|
||||
if (~properties.flags & boxPassableFlag) {
|
||||
properties.flags |= boxPassableFlag;
|
||||
foreach (i, ref actor; actors) {
|
||||
if (actorsProperties[i].isPassable) continue;
|
||||
if (actorsProperties[i].flags & boxPassableFlag) continue;
|
||||
if (wall.hasIntersection(actor)) {
|
||||
// Push actor.
|
||||
auto wallTop = wall.position.y;
|
||||
|
@ -500,12 +492,12 @@ struct BoxWorld {
|
|||
// Squish actor.
|
||||
squishedIdsBuffer.append(cast(BaseBoxId) (i + 1));
|
||||
}
|
||||
} else if (actorsProperties[i].isRiding) {
|
||||
} else if (actorsProperties[i].flags & boxRidingFlag) {
|
||||
// Carry actor.
|
||||
moveActorY(cast(BaseBoxId) (i + 1), move.y);
|
||||
}
|
||||
}
|
||||
properties.isPassable = false;
|
||||
properties.flags &= ~boxPassableFlag;
|
||||
}
|
||||
}
|
||||
return squishedIdsBuffer[];
|
||||
|
|
|
@ -15,7 +15,6 @@ import joka.ascii;
|
|||
import joka.containers;
|
||||
import joka.io;
|
||||
import joka.types;
|
||||
import joka.unions;
|
||||
|
||||
@safe @nogc nothrow:
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue