v0.7.5: overhauled Goo's level layout, including new level builder
This commit is contained in:
parent
52ed3dda2c
commit
c741b82f10
|
@ -139,22 +139,6 @@ public abstract class RegularLevel extends Level {
|
|||
|
||||
protected abstract Painter painter();
|
||||
|
||||
protected float waterFill(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected int waterSmoothing(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected float grassFill(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected int grassSmoothing(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
protected int nTraps() {
|
||||
return Random.NormalIntRange( 1, 3+(Dungeon.depth/3) );
|
||||
}
|
||||
|
|
|
@ -23,15 +23,17 @@ package com.shatteredpixel.shatteredpixeldungeon.levels;
|
|||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.Bones;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.Actor;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.actors.mobs.Goo;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Heap;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.items.Item;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.Builder;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.LoopBuilder;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.builders.FigureEightBuilder;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.SewerPainter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.secret.RatKingRoom;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.sewerboss.GooBossRoom;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.sewerboss.SewerBossEntranceRoom;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.sewerboss.SewerBossExitRoom;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.StandardRoom;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.scenes.GameScene;
|
||||
import com.watabou.utils.Bundle;
|
||||
|
@ -51,14 +53,23 @@ public class SewerBossLevel extends SewerLevel {
|
|||
@Override
|
||||
protected ArrayList<Room> initRooms() {
|
||||
ArrayList<Room> initRooms = new ArrayList<>();
|
||||
initRooms.add ( roomEntrance = roomExit = new SewerBossEntranceRoom());
|
||||
|
||||
//TODO it would be nice for these rooms to have some custom tile visuals
|
||||
initRooms.add( roomEntrance = new SewerBossEntranceRoom() );
|
||||
initRooms.add( roomExit = new SewerBossExitRoom() );
|
||||
|
||||
int standards = standardRooms();
|
||||
for (int i = 0; i < standards; i++) {
|
||||
initRooms.add(StandardRoom.createRoom());
|
||||
StandardRoom s = StandardRoom.createRoom();
|
||||
//force to normal size
|
||||
s.setSizeCat(0, 0);
|
||||
initRooms.add(s);
|
||||
}
|
||||
|
||||
initRooms.add(GooBossRoom.randomGooRoom());
|
||||
//TODO need to improve the visual appearance of goo's nest
|
||||
GooBossRoom gooRoom = GooBossRoom.randomGooRoom();
|
||||
initRooms.add(gooRoom);
|
||||
((FigureEightBuilder)builder).setLandmarkRoom(gooRoom);
|
||||
initRooms.add(new RatKingRoom());
|
||||
return initRooms;
|
||||
}
|
||||
|
@ -70,29 +81,18 @@ public class SewerBossLevel extends SewerLevel {
|
|||
}
|
||||
|
||||
protected Builder builder(){
|
||||
return new LoopBuilder()
|
||||
return new FigureEightBuilder()
|
||||
.setLoopShape( 2 , Random.Float(0.4f, 0.7f), Random.Float(0f, 0.5f))
|
||||
.setPathLength(1f, new float[]{1})
|
||||
.setTunnelLength(new float[]{0, 3, 1}, new float[]{1});
|
||||
.setTunnelLength(new float[]{1, 2}, new float[]{1});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float waterFill(){
|
||||
return 0.50f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int waterSmoothing(){
|
||||
return 5;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float grassFill() {
|
||||
return 0.20f;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int grassSmoothing() {
|
||||
return 4;
|
||||
protected Painter painter() {
|
||||
return new SewerPainter()
|
||||
.setWater(0.50f, 5)
|
||||
.setGrass(0.20f, 4)
|
||||
.setTraps(nTraps(), trapClasses(), trapChances());
|
||||
}
|
||||
|
||||
protected int nTraps() {
|
||||
|
|
|
@ -0,0 +1,278 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2019 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.shatteredpixel.shatteredpixeldungeon.levels.builders;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.connection.ConnectionRoom;
|
||||
import com.watabou.utils.PointF;
|
||||
import com.watabou.utils.Random;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class FigureEightBuilder extends RegularBuilder {
|
||||
|
||||
//These methods allow for the adjusting of the shape of the loop
|
||||
//by default the loop is a perfect circle, but it can be adjusted
|
||||
|
||||
//increasing the exponent will increase the the curvature, making the loop more oval shaped.
|
||||
private int curveExponent = 0;
|
||||
|
||||
//This is a percentage (range 0-1) of the intensity of the curve function
|
||||
// 0 makes for a perfect linear curve (circle)
|
||||
// 1 means the curve is completely determined by the curve exponent
|
||||
private float curveIntensity = 1;
|
||||
|
||||
//Adjusts the starting point along the loop.
|
||||
// a common example, setting to 0.25 will make for a short fat oval instead of a long one.
|
||||
private float curveOffset = 0;
|
||||
|
||||
public FigureEightBuilder setLoopShape(int exponent, float intensity, float offset){
|
||||
this.curveExponent = Math.abs(exponent);
|
||||
curveIntensity = intensity % 1f;
|
||||
curveOffset = offset % 0.5f;
|
||||
return this;
|
||||
}
|
||||
|
||||
private float targetAngle( float percentAlong ){
|
||||
percentAlong += curveOffset;
|
||||
return 360f * (float)(
|
||||
curveIntensity * curveEquation(percentAlong)
|
||||
+ (1-curveIntensity)*(percentAlong)
|
||||
- curveOffset);
|
||||
}
|
||||
|
||||
private double curveEquation( double x ){
|
||||
return Math.pow(4, 2*curveExponent)
|
||||
*(Math.pow((x % 0.5f )-0.25, 2*curveExponent + 1))
|
||||
+ 0.25 + 0.5*Math.floor(2*x);
|
||||
}
|
||||
|
||||
private Room landmarkRoom;
|
||||
|
||||
public FigureEightBuilder setLandmarkRoom(Room room){
|
||||
landmarkRoom = room;
|
||||
return this;
|
||||
}
|
||||
|
||||
ArrayList<Room> firstLoop, secondLoop;
|
||||
PointF firstLoopCenter, secondLoopCenter;
|
||||
|
||||
@Override
|
||||
public ArrayList<Room> build(ArrayList<Room> rooms) {
|
||||
setupRooms(rooms);
|
||||
|
||||
//TODO might want to make this able to work without an exit. Probably a random room would be landmark and the landmark room would become exit
|
||||
if (landmarkRoom == null){
|
||||
landmarkRoom = Random.element(multiConnections);
|
||||
}
|
||||
|
||||
if (multiConnections.contains(landmarkRoom)){
|
||||
multiConnections.remove(landmarkRoom);
|
||||
}
|
||||
|
||||
float startAngle = Random.Float(0, 180);
|
||||
|
||||
int roomsOnLoop = (int)(multiConnections.size()*pathLength) + Random.chances(pathLenJitterChances);
|
||||
roomsOnLoop = Math.min(roomsOnLoop, multiConnections.size());
|
||||
|
||||
int roomsOnFirstLoop = roomsOnLoop/2;
|
||||
if (roomsOnLoop % 2 == 1) roomsOnFirstLoop += Random.Int(2);
|
||||
|
||||
firstLoop = new ArrayList<>();
|
||||
float[] pathTunnels = pathTunnelChances.clone();
|
||||
for (int i = 0; i <= roomsOnFirstLoop; i++){
|
||||
if (i == 0)
|
||||
firstLoop.add(landmarkRoom);
|
||||
else
|
||||
firstLoop.add(multiConnections.remove(0));
|
||||
|
||||
int tunnels = Random.chances(pathTunnels);
|
||||
if (tunnels == -1){
|
||||
pathTunnels = pathTunnelChances.clone();
|
||||
tunnels = Random.chances(pathTunnels);
|
||||
}
|
||||
pathTunnels[tunnels]--;
|
||||
|
||||
for (int j = 0; j < tunnels; j++){
|
||||
firstLoop.add(ConnectionRoom.createRoom());
|
||||
}
|
||||
}
|
||||
if (entrance != null) firstLoop.add((firstLoop.size()+1)/2, entrance);
|
||||
|
||||
int roomsOnSecondLoop = roomsOnLoop - roomsOnFirstLoop;
|
||||
|
||||
secondLoop = new ArrayList<>();
|
||||
for (int i = 0; i <= roomsOnSecondLoop; i++){
|
||||
if (i == 0)
|
||||
secondLoop.add(landmarkRoom);
|
||||
else
|
||||
secondLoop.add(multiConnections.remove(0));
|
||||
|
||||
int tunnels = Random.chances(pathTunnels);
|
||||
if (tunnels == -1){
|
||||
pathTunnels = pathTunnelChances.clone();
|
||||
tunnels = Random.chances(pathTunnels);
|
||||
}
|
||||
pathTunnels[tunnels]--;
|
||||
|
||||
for (int j = 0; j < tunnels; j++){
|
||||
secondLoop.add(ConnectionRoom.createRoom());
|
||||
}
|
||||
}
|
||||
if (exit != null) secondLoop.add((secondLoop.size()+1)/2, exit);
|
||||
|
||||
landmarkRoom.setSize();
|
||||
landmarkRoom.setPos(0, 0);
|
||||
|
||||
Room prev = landmarkRoom;
|
||||
float targetAngle;
|
||||
for (int i = 1; i < firstLoop.size(); i++){
|
||||
Room r = firstLoop.get(i);
|
||||
targetAngle = startAngle + targetAngle( i / (float)firstLoop.size());
|
||||
if (placeRoom(rooms, prev, r, targetAngle) != -1) {
|
||||
prev = r;
|
||||
if (!rooms.contains(prev))
|
||||
rooms.add(prev);
|
||||
} else {
|
||||
//FIXME this is lazy, there are ways to do this without relying on chance
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME this is still fairly chance reliant
|
||||
// should just write a general function for stitching two rooms together in builder
|
||||
while (!prev.connect(landmarkRoom)){
|
||||
|
||||
ConnectionRoom c = ConnectionRoom.createRoom();
|
||||
if (placeRoom(firstLoop, prev, c, angleBetweenRooms(prev, entrance)) == -1){
|
||||
return null;
|
||||
}
|
||||
firstLoop.add(c);
|
||||
rooms.add(c);
|
||||
prev = c;
|
||||
}
|
||||
|
||||
prev = landmarkRoom;
|
||||
startAngle += 180f;
|
||||
for (int i = 1; i < secondLoop.size(); i++){
|
||||
Room r = secondLoop.get(i);
|
||||
targetAngle = startAngle + targetAngle( i / (float)secondLoop.size());
|
||||
if (placeRoom(rooms, prev, r, targetAngle) != -1) {
|
||||
prev = r;
|
||||
if (!rooms.contains(prev))
|
||||
rooms.add(prev);
|
||||
} else {
|
||||
//FIXME this is lazy, there are ways to do this without relying on chance
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
//FIXME this is still fairly chance reliant
|
||||
// should just write a general function for stitching two rooms together in builder
|
||||
while (!prev.connect(landmarkRoom)){
|
||||
|
||||
ConnectionRoom c = ConnectionRoom.createRoom();
|
||||
if (placeRoom(secondLoop, prev, c, angleBetweenRooms(prev, entrance)) == -1){
|
||||
return null;
|
||||
}
|
||||
secondLoop.add(c);
|
||||
rooms.add(c);
|
||||
prev = c;
|
||||
}
|
||||
|
||||
if (shop != null) {
|
||||
float angle;
|
||||
int tries = 10;
|
||||
do {
|
||||
angle = placeRoom(firstLoop, entrance, shop, Random.Float(360f));
|
||||
tries--;
|
||||
} while (angle == -1 && tries >= 0);
|
||||
if (angle == -1) return null;
|
||||
}
|
||||
|
||||
firstLoopCenter = new PointF();
|
||||
for (Room r : firstLoop){
|
||||
firstLoopCenter.x += (r.left + r.right)/2f;
|
||||
firstLoopCenter.y += (r.top + r.bottom)/2f;
|
||||
}
|
||||
firstLoopCenter.x /= firstLoop.size();
|
||||
firstLoopCenter.y /= firstLoop.size();
|
||||
|
||||
secondLoopCenter = new PointF();
|
||||
for (Room r : secondLoop){
|
||||
secondLoopCenter.x += (r.left + r.right)/2f;
|
||||
secondLoopCenter.y += (r.top + r.bottom)/2f;
|
||||
}
|
||||
secondLoopCenter.x /= secondLoop.size();
|
||||
secondLoopCenter.y /= secondLoop.size();
|
||||
|
||||
ArrayList<Room> branchable = new ArrayList<>(firstLoop);
|
||||
branchable.addAll(secondLoop);
|
||||
branchable.remove(landmarkRoom); //remove once so it isn't present twice
|
||||
|
||||
ArrayList<Room> roomsToBranch = new ArrayList<>();
|
||||
roomsToBranch.addAll(multiConnections);
|
||||
roomsToBranch.addAll(singleConnections);
|
||||
weightRooms(branchable);
|
||||
createBranches(rooms, branchable, roomsToBranch, branchTunnelChances);
|
||||
|
||||
findNeighbours(rooms);
|
||||
|
||||
for (Room r : rooms){
|
||||
for (Room n : r.neigbours){
|
||||
if (!n.connected.containsKey(r)
|
||||
&& Random.Float() < extraConnectionChance){
|
||||
r.connect(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rooms;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float randomBranchAngle( Room r ) {
|
||||
PointF center;
|
||||
if (firstLoop.contains(r)){
|
||||
center = firstLoopCenter;
|
||||
} else {
|
||||
center = secondLoopCenter;
|
||||
}
|
||||
if (center == null)
|
||||
return super.randomBranchAngle( r );
|
||||
else {
|
||||
//generate four angles randomly and return the one which points closer to the center
|
||||
float toCenter = angleBetweenPoints( new PointF((r.left + r.right)/2f, (r.top + r.bottom)/2f), center);
|
||||
if (toCenter < 0) toCenter += 360f;
|
||||
|
||||
float currAngle = Random.Float(360f);
|
||||
for( int i = 0; i < 4; i ++){
|
||||
float newAngle = Random.Float(360f);
|
||||
if (Math.abs(toCenter - newAngle) < Math.abs(toCenter - currAngle)){
|
||||
currAngle = newAngle;
|
||||
}
|
||||
}
|
||||
return currAngle;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -86,10 +86,9 @@ public class LoopBuilder extends RegularBuilder {
|
|||
ArrayList<Room> loop = new ArrayList<>();
|
||||
int roomsOnLoop = (int)(multiConnections.size()*pathLength) + Random.chances(pathLenJitterChances);
|
||||
roomsOnLoop = Math.min(roomsOnLoop, multiConnections.size());
|
||||
roomsOnLoop++;
|
||||
|
||||
float[] pathTunnels = pathTunnelChances.clone();
|
||||
for (int i = 0; i < roomsOnLoop; i++){
|
||||
for (int i = 0; i <= roomsOnLoop; i++){
|
||||
if (i == 0)
|
||||
loop.add(entrance);
|
||||
else
|
||||
|
@ -137,14 +136,6 @@ public class LoopBuilder extends RegularBuilder {
|
|||
prev = c;
|
||||
}
|
||||
|
||||
loopCenter = new PointF();
|
||||
for (Room r : loop){
|
||||
loopCenter.x += (r.left + r.right)/2f;
|
||||
loopCenter.y += (r.top + r.bottom)/2f;
|
||||
}
|
||||
loopCenter.x /= loop.size();
|
||||
loopCenter.y /= loop.size();
|
||||
|
||||
if (shop != null) {
|
||||
float angle;
|
||||
int tries = 10;
|
||||
|
@ -155,6 +146,14 @@ public class LoopBuilder extends RegularBuilder {
|
|||
if (angle == -1) return null;
|
||||
}
|
||||
|
||||
loopCenter = new PointF();
|
||||
for (Room r : loop){
|
||||
loopCenter.x += (r.left + r.right)/2f;
|
||||
loopCenter.y += (r.top + r.bottom)/2f;
|
||||
}
|
||||
loopCenter.x /= loop.size();
|
||||
loopCenter.y /= loop.size();
|
||||
|
||||
ArrayList<Room> branchable = new ArrayList<>(loop);
|
||||
|
||||
ArrayList<Room> roomsToBranch = new ArrayList<>();
|
||||
|
|
|
@ -30,35 +30,11 @@ import com.watabou.utils.Point;
|
|||
|
||||
public class SewerBossEntranceRoom extends EntranceRoom {
|
||||
|
||||
@Override
|
||||
public int minWidth() {
|
||||
return 9;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int maxWidth() {
|
||||
return 9;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int minHeight() {
|
||||
return 6;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int maxHeight() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
//TODO perhaps I just want to deny all top-side connections
|
||||
@Override
|
||||
public boolean canConnect(Point p) {
|
||||
//refuses connections on the center 3 tiles on the top side, and the top tile along left/right
|
||||
return super.canConnect(p)
|
||||
&& !(p.y == top && p.x >= (left + (width()/2 - 1)) && p.x <= (left + (width()/2 + 1)))
|
||||
&& p.y != top+1;
|
||||
}
|
||||
|
||||
public void paint(Level level ) {
|
||||
|
||||
Painter.fill( level, this, Terrain.WALL );
|
||||
|
@ -67,9 +43,6 @@ public class SewerBossEntranceRoom extends EntranceRoom {
|
|||
Painter.fill( level, left+1, top+1, width()-2, 1, Terrain.WALL_DECO);
|
||||
Painter.fill( level, left+1, top+2, width()-2, 1, Terrain.WATER);
|
||||
|
||||
Painter.set( level, left+width()/2, top+1, Terrain.LOCKED_EXIT);
|
||||
level.exit = level.pointToCell(new Point(left+width()/2, top+1));
|
||||
|
||||
do {
|
||||
level.entrance = level.pointToCell(random(3));
|
||||
} while (level.findMob(level.entrance) != null);
|
||||
|
@ -78,8 +51,8 @@ public class SewerBossEntranceRoom extends EntranceRoom {
|
|||
for (Room.Door door : connected.values()) {
|
||||
door.set( Room.Door.Type.REGULAR );
|
||||
|
||||
if (door.y == top){
|
||||
Painter.set( level, door.x, door.y+1, Terrain.WATER);
|
||||
if (door.y == top || door.y == top+1){
|
||||
Painter.drawInside( level, this, door, 1, Terrain.WATER);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Pixel Dungeon
|
||||
* Copyright (C) 2012-2015 Oleg Dolya
|
||||
*
|
||||
* Shattered Pixel Dungeon
|
||||
* Copyright (C) 2014-2019 Evan Debenham
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
package com.shatteredpixel.shatteredpixeldungeon.levels.rooms.sewerboss;
|
||||
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Level;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.Terrain;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.painters.Painter;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.Room;
|
||||
import com.shatteredpixel.shatteredpixeldungeon.levels.rooms.standard.ExitRoom;
|
||||
import com.watabou.utils.Point;
|
||||
|
||||
public class SewerBossExitRoom extends ExitRoom {
|
||||
|
||||
@Override
|
||||
public int minWidth() {
|
||||
return Math.max(super.minWidth(), 7);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int minHeight() {
|
||||
return Math.max(super.minHeight(), 7);
|
||||
}
|
||||
|
||||
public void paint(Level level) {
|
||||
|
||||
Painter.fill( level, this, Terrain.WALL );
|
||||
Painter.fill( level, this, 1, Terrain.EMPTY );
|
||||
|
||||
for (Room.Door door : connected.values()) {
|
||||
door.set( Room.Door.Type.REGULAR );
|
||||
}
|
||||
|
||||
Point c = center();
|
||||
|
||||
Painter.fill( level, c.x-1, c.y-1, 3, 1, Terrain.WALL );
|
||||
Painter.fill( level, c.x-1, c.y , 3, 1, Terrain.WALL_DECO );
|
||||
Painter.fill( level, c.x-1, c.y+1, 3, 1, Terrain.WATER );
|
||||
|
||||
level.exit = level.pointToCell(c);
|
||||
Painter.set( level, level.exit, Terrain.LOCKED_EXIT );
|
||||
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user