diff --git a/Deliverables/.DS_Store b/Deliverables/.DS_Store
deleted file mode 100644
index 14ea2def..00000000
Binary files a/Deliverables/.DS_Store and /dev/null differ
diff --git a/Deliverables/Obligatorisk Oppgave3/ClassDiagramMandatroyAssignment3.png b/Deliverables/Obligatorisk Oppgave3/ClassDiagramMandatroyAssignment3.png
new file mode 100644
index 00000000..5418fe9b
Binary files /dev/null and b/Deliverables/Obligatorisk Oppgave3/ClassDiagramMandatroyAssignment3.png differ
diff --git a/Deliverables/Obligatorisk Oppgave3/ClassDiagramMandatroyAssignment3.uml b/Deliverables/Obligatorisk Oppgave3/ClassDiagramMandatroyAssignment3.uml
new file mode 100644
index 00000000..740cdfb6
--- /dev/null
+++ b/Deliverables/Obligatorisk Oppgave3/ClassDiagramMandatroyAssignment3.uml
@@ -0,0 +1,389 @@
+
+
+ JAVA
+ inf112.skeleton.app
+
+ inf112.skeleton.app.cards.ProgramCard
+ inf112.skeleton.app.screens.YouWinScreen
+ inf112.skeleton.app.objects.Laser
+ inf112.skeleton.app.RallyGame
+ inf112.skeleton.app.Main
+ inf112.skeleton.app.cards.Deck
+ inf112.skeleton.app.Player
+ inf112.skeleton.app.PlayerSorter
+ inf112.skeleton.app.enums.Direction
+ inf112.skeleton.app.BoardLayers
+ inf112.skeleton.app.screens.GameScreen
+ inf112.skeleton.app.screens.StandardScreen
+ inf112.skeleton.app.screens.MenuScreen
+ inf112.skeleton.app.Board
+ inf112.skeleton.app.GifDecoder
+ inf112.skeleton.app.objects.Flag
+ inf112.skeleton.app.screens.LoadingScreen
+ inf112.skeleton.app.enums.TileID
+ inf112.skeleton.app.enums.Rotate
+ inf112.skeleton.app.objects.RotatePad
+ inf112.skeleton.app.screens.GifScreen
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Production
+ private
+
+
diff --git a/Deliverables/Obligatorisk Oppgave3/ObligatoriskOppgave3.md b/Deliverables/Obligatorisk Oppgave3/ObligatoriskOppgave3.md
new file mode 100644
index 00000000..361de8b9
--- /dev/null
+++ b/Deliverables/Obligatorisk Oppgave3/ObligatoriskOppgave3.md
@@ -0,0 +1,290 @@
+# Mandatory Assignment 3
+Team: error_no_brain_found
+
+## Task 1 - Team and project
+### Meeting minutes
+[Møte 4](https://github.com/inf112-v20/error_brain_not_found/wiki/Møte-4.)
+[Møte 5](https://github.com/inf112-v20/error_brain_not_found/wiki/Møte-5.)
+[Møte 6](https://github.com/inf112-v20/error_brain_not_found/wiki/Møte-6)
+[Møte 7](https://github.com/inf112-v20/error_brain_not_found/wiki/Møte-7)
+
+The meeting minutes ended up looking a bit lack of words. Since we was more busy with doing code, explaining code to each
+other, and handout `Issues` to everyone, in the meeting.
+
+### Roles
+The roles in the team work ok. The teamleader takes responsibility of tasks like how to perform meetings in this new
+situation, takes initiatives for making meeting minutes and so on. The teamleader and customer contact
+have been developing code, the tester has been making tests to this code. Also the UX designer has started to work on his tasks.
+We do not want to change teamlead or contact.
+For more depth information on the roles see [ObligatoriskOppgave2](https://github.com/inf112-v20/error_brain_not_found/blob/develop/Deliverables/Obligatorisk%20Oppgave2/ObligatoriskOppgave2.md),
+under `Roles`.
+
+### Experiences with the team or project-methods
+We are getting better at using issues, tags in issues and the projectboard. When a task needs to be done,
+we make user stories, acceptance criteria's and tasks. This is copied into the issue, and the tasks are made as
+check boxes so that we can see progress in the issue. Also an own issue for tests for this task is made and is tagging the issue
+it should be testing, with acceptance criteria as tests to be made. This gives us a great overview of who is doing what,
+and a great workflow because we can always see what to do next.
+
+### Do you think you have made good choices? If not, explain
+In general yes, we think it was smart to device the team into roles like Developers, Tester etc, because then everyone know
+what to do. On the other hand, these roles have some overlap, for example that maybe the tester sees something that needs to be fixed, can not
+reach some code, or that the developer/UX-designer needs a specific test. We are then assigning issues to each other and specify the task needs
+to be done, but sometimes this results in a lot of waiting for the person requesting these changing and the person needs to get this done before
+doing anything else. We have discussed how this can be handled, and agreed on that small fixes can be done even though it is not
+your area of responsibility.
+
+### Retrospective
+Working in this iteration has been different. We have not been able to meet in person and all our communication has moved
+online. This have come with its own pros and cons. It took some time for everyone to get used to the new situation, so the first
+week after the "campus-ban" wasn't the most productive. When everyone got in to the new situation we started to make the
+best of it. When people need help about something, they send someone in the team a message. And they often get the
+answer faster now then what they did before. Meetings are going fine for now, but it will be harder as longer this ban
+keeps on. I think the way we parted the roles and made us survived the transition in a good way. Every role has one main
+responsibility area. When you have to move closer to someone else's area and you meet a wall we are fast to help each other
+out. Also we have agreed on that if it is small changes/additions, this can be fixed even though it is not you area.
+
+We have have some work to do on planing what specific elements of the project need, so every member of the group have what
+they need. In some cases the test require specific methods, that the tester often has to ask for. So if we start planing better
+when we get the idea, we think this could delete that obstacle.
+
+The group is more proactive now and uses the `Project Board` more to see what needs to be done. When they are finished with their
+task, and have some time leftover, they find something on the board like a `Bug` or something in the `Backlog`. They also communicate
+this to the team, so everyone in the team have an idea of what is going on at the same time. So we feel the communication in
+the team is getting better.
+
+#### Improvement points from retrospective
+* Make concrete tasks for each user story.
+* Fix small changes even though it is not you area.
+* Follow up issues on project board.
+
+### Prioritization in the future
+This iteration we have prioritized, and are done with:
+* Holes: when a player is on hole it is respawned
+* Lasers: making them work properly (get stopped by player and let player take damage)
+* Damage: Let player take damage
+* Game loop: When space is pressed the players use their programcards.
+* Menu-screen: Choose different boards for the game
+* Flags: Let the player pick up flags so it can win
+* Rotatepad: rotate a player on a rotatepad
+
+We have prioritized to get each component of the game to work properly (walls, lasers), so that we can make
+a working game loop with all the different parts working together.
+
+Next iteration we will focus on:
+* Show cards: Let the player see the cards on the screen
+* Belts: Make belts
+* Game loop: Get a working game loop
+
+![Screenshot Project board](ScreenshotProjectBoard.png)
+
+### Group dynamic and communication
+In general communication works fine, we communicate over slack and assign tasks to each other by making
+issues and add them to project board. As mentioned before, because some overlapping of the different roles in the team,
+it can be a bit challenging to wait for others to respond when you are working on something. Most of the team are communicating
+great over slack and are doing tasks assigned to them, but we can not get a hold of one of the team-members. We assign issues with tasks and
+follow up with message over slack, but experience very little to no feedback.
+
+## Task 2 - Requirements
+### User stories:
+#### Holes
+
+User story:
+As a player I want to respawn if I end up on a hole, so that I can continue the game from backup.
+
+Acceptance-criteria:
+* If I go on a tile where there is a hole I want to be respawned at my backup.
+
+Tasks:
+* Make a method that tells if you are on a hole
+* Test that you are respawned when on a hole
+
+#### Laser
+User-story:
+As a player I want the laser to be able to hit me, so that I take damage.
+
+Acceptance-criteria:
+* If a laser is activated and player is standing in its shooting line, it gives player damage.
+* If a laser is activated and player is not standing in its shooting line, it does not give player damage.
+
+Tasks:
+* Make a method that tells if a laser is hitting a player
+* Make a method that makes the player take damage
+* Make tests for when laser is hitting player
+
+User-story:
+As a player I want the laser not to hit me when it is blocked by objects on the board, so that I do not take damage.
+
+Acceptance-criteria:
+If a laser is activated and player is standing in its shooting line but is blocked, then player does not get damage.
+
+Tasks:
+* Make a method to tell if a laser is blocked, or make laser object know how far it can go by checking board.
+* Test if the range of the specific laser is correct.
+* Test that a player is not damaged when out of range of laser.
+
+#### Belts
+User-story:
+As player standing on a belt, I want to be moved as many steps as the belt is moving, so that I can get closer to my goal.
+
+Acceptance-criteria:
+* If a player is standing on a belt and the belt is moving, then the player will move.
+* If a player is on a belt, it moves as many steps as the belt does (express or regular)
+
+Tasks:
+* Make a method to tell if you are on a belt.
+* Let the belt know if it should move or not and how fast it should go
+* Make a method to move any player on the belt
+
+User-story:
+As a player standing on a belt, I want to be moved in the same direction the belt is moving, so that I can stay on the belt.
+
+Acceptance-criteria:
+* If a player is standing on the corner and the belt is moving, then the player changes direction with the belt.
+
+Task:
+* Make a method to tell if player is on the corner of the belt and what direction it
+should have
+
+**NOT FINNISHED**, will be continued to next sprint.
+
+#### RotatePads
+User-story:
+As a user I want to get turned if I walk on a rotate pad
+
+Acceptance-criteria:
+when I move to a tile with a rotate-wheel I want to be turned in the direction of the rotate pad
+
+Tasks:
+* make a method that tells if player i on rotate pad and then rotate player
+* test that player is rotated in correct direction
+
+#### MenuScreen
+User-Story:
+As a user of the game I want to be able to choose different board layouts, so that I can have a new challenge in the game.
+
+Acceptance-criteria:
+If I choose a board-layout, this is the layout that shows when I start the game
+
+Tasks:
+* Make methods for choosing board
+* Make graphics for choosing board
+
+#### Life on robots
+User-Story:
+As a player I want my robot to be able to take damage, so that my robot can die
+
+Acceptance-criteria:
+If a laser hits me, I want to recieve damage
+
+Tasks:
+Make methods for robots to take damage
+
+#### Damagetoken
+User-Story:
+As a player I want my robot to have a Token-bar, to see when or if my robot gets hurt
+
+Acceptance-criteria:
+* When i get 10 damage tokens, I want my robot to die and respawn
+* When i get 5 or more damage tokens, then the program cards will 'lock up' starting from register 5
+* When i get x damage tokens, I will get x less program cards
+
+Tasks:
+* Make a GUI for visible damage tokens for the robots
+* Make methods to recieve damage tokens
+* Make methods to recieve less programs cards based on damage tokens
+
+#### Lifetoken
+User-Story:
+As a player I want to have Life tokens, to see how many lives I have left
+
+Acceptance-criteria:
+* If my robot gets 10 damage tokens, I lose a life token
+* If my life tokens are depleted, then im permanently out of the game
+
+Tasks:
+* Make a GUI to visualize life tokens
+* Make a method that removes life tokens when robots die.
+* Make a method that robots do not respawn after losing all life tokens
+
+#### See the cards
+User-story:
+As a player I want to be able to see the cards, so that I can plan my program.
+
+Acceptance-citeria:
+* When I have drawn the cards, the cards are displayed in front of me on the screen.
+
+Tasks:
+* Make graphics for showing cards
+* Manual test
+
+This is not done, will continue on next sprint
+
+#### Flags
+User-story:
+As a user I want to go on flags, so that I can win the game.
+
+Acceptance-criteria:
+* If I go on a flag, this flag is picked up.
+* If I pick up all flags in correct order, I win.
+* If I pick up flags in incorrect order, the flag is not picked up.
+
+Tasks:
+* Create a function to tell i you can pick up a flag
+* Create flags with flagnumber and position
+* Check if all flags are picked up in correct order
+* Make tests for flags
+
+#### Game loop
+User-story:
+As a player I want the game to go in a loop, so that events happen in a specific order.
+
+Acceptance-criteria:
+When the game starts, it goes through the fases and the rounds.
+
+Tasks:
+* Make loop for the game.
+* Test that events happen in right order
+* Manual tests
+
+A testing version is up, but this is going to be continued on next sprint.
+
+#### Main criteria for MVP
+*[x] The game should be able to run, show a board with starting robot and programcards to this robot.
+*[ ] The player is able to pick programcards and place them so that the robot can move.
+*[ ] The game should be able to do a round, and do the phases in the correct order in that round.
+*[x] The robot should be able to win by going to the flags in a specific order.
+*[x] The robot is stopped by walls, pushed by other players and respawned when outside board/on hole.
+*[ ] The robot should be able to do a powerdown.
+*[x] The laser can shoot the robots and the robots take damage.
+*[ ] The belts move so the player can be moved by belts.
+
+## Task 3 - Productdelivery and codequality
+### Manual tests
+The start-screen goes away after clicking on it.
+* start the game then click somewhere on the screen. Then the menu-screen should come.
+
+Game loop:
+* When the game has started press space once.
+* Then all robots will use one programcard in turn, 5 times. (5 rounds)
+* Press space again after all robots have moved and the robots will do five more rounds.
+
+Laser:
+* Press on of the keyboard-arrows and the lasers will be activated.
+* Stear your player in front of a laser. The laser should be stopped by a player.
+
+Menu-screen:
+* Click on the start-menu (a picture). Then a screen with a roll-down menu and start and exit buttons should show.
+* Choose your board by choosing from the roll-down menu then click start. The board should show with players on it.
+
+### Bugs
+Game sometimes crashes after clicking on start menu
+
+### Comment to automatic build tests
+Travis does not support the language `Java` on their Windows Build Environment. But 3/5 in our group run windows and it
+runs on their computer.
+
+### Comment to classdiagram
+The project is getting big so the diagram is no only the classes, if you want to se the content of the classes in the UML
+there is possible to put it on in the `ClassDiagramMandatoryAssignment3.uml` in the `Deliverables/Obligatorisk Oppgave3`
+folder.
diff --git a/Deliverables/Obligatorisk Oppgave3/ScreenshotProjectBoard.png b/Deliverables/Obligatorisk Oppgave3/ScreenshotProjectBoard.png
new file mode 100644
index 00000000..db84c099
Binary files /dev/null and b/Deliverables/Obligatorisk Oppgave3/ScreenshotProjectBoard.png differ
diff --git a/README.md b/README.md
index 7d3436b9..0a4bdda0 100644
--- a/README.md
+++ b/README.md
@@ -5,8 +5,11 @@
Simple skeleton with libgdx.
## How to run
-Clone the repo from github to you computer then:
-Open the repo and go to `src/main/java/inf112/skeleton/app/Main.java` and run `main` function.
+The program runs `java` and `maven`, these need to be installed.
+Every text-editor that can run version control system, can be used. We recommend IntelliJ IDEA.
+Clone the repo from github to you computer: `git clone https://github.com/inf112-v20/error_brain_not_found.git`
+Then open `pom.xml` in IntelliJ and the IntelliJ will build the project for you.
+Then open the repo and go to `src/main/java/inf112/skeleton/app/Main.java` and run `main` function.
## Known bugs
Currently throws "WARNING: An illegal reflective access operation has occurred",
diff --git a/assets/Dizzy_Dash.tmx b/assets/Dizzy_Dash.tmx
deleted file mode 100644
index cc221fd8..00000000
--- a/assets/Dizzy_Dash.tmx
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
-
-
-5,50,5,131,5,5,5,5,5,5,5,5,5,5,5,5,
-5,50,129,5,5,19,14,14,20,5,5,19,14,14,20,5,
-33,44,5,5,5,13,5,54,21,53,5,13,15,54,21,5,
-50,123,5,5,5,13,54,7,21,5,5,13,54,5,21,5,
-50,5,5,5,5,27,22,22,28,5,53,27,22,22,28,5,
-121,5,5,5,5,5,5,5,53,5,5,5,5,53,5,5,
-122,5,5,5,5,5,53,5,5,5,5,53,5,5,5,5,
-49,5,5,5,5,19,14,14,20,53,5,19,14,14,20,5,
-49,124,5,5,5,13,5,54,21,5,5,13,7,54,21,5,
-43,34,5,5,5,13,54,15,21,5,53,13,54,5,21,5,
-5,49,130,5,5,27,22,22,28,5,5,27,22,22,28,5,
-5,49,5,132,5,5,5,5,5,5,5,5,5,5,5,5
-
-
-
-
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,39,39,39,39,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,47,0,0,0,0,47,0,0,0,
-0,0,0,0,0,0,0,47,0,0,0,0,47,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,39,39,39,39,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
-
-
-
-0,0,0,0,0,0,31,0,31,0,0,31,0,31,0,0,
-0,0,31,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,31,23,30,0,0,0,0,0,0,0,0,0,0,23,
-0,0,0,0,0,0,0,0,0,38,0,0,0,30,0,0,
-0,0,0,16,30,0,0,0,0,0,0,0,0,0,0,23,
-0,0,0,0,0,0,0,31,0,0,0,0,31,0,0,0,
-31,31,0,0,0,0,0,29,0,0,0,0,29,0,0,0,
-0,0,0,8,30,0,0,0,0,0,0,0,0,0,0,23,
-0,0,0,0,0,0,23,0,0,0,46,0,0,0,0,0,
-0,0,29,23,30,0,0,0,0,0,0,0,0,0,0,23,
-0,0,29,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,29,0,29,0,0,29,0,29,0,0
-
-
-
-
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,71,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,55,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,63,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
-
-
-
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
-
-
diff --git a/assets/Risky_Exchange.tmx b/assets/Risky_Exchange.tmx
deleted file mode 100644
index a8bfa9a8..00000000
--- a/assets/Risky_Exchange.tmx
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
-
-
-5,50,5,131,5,6,5,49,5,5,49,5,50,5,49,15,
-5,50,129,5,5,5,5,49,5,50,49,5,50,5,5,5,
-33,44,5,5,5,5,5,49,5,50,49,5,50,5,5,5,
-50,123,5,5,52,52,52,53,5,50,49,5,53,52,52,52,
-50,5,5,5,5,5,5,5,5,50,49,5,5,5,5,5,
-121,5,5,5,22,22,22,22,22,5,5,51,51,51,51,51,
-122,5,5,5,5,52,52,52,52,5,5,52,52,52,52,52,
-49,5,5,5,5,5,5,5,7,21,49,5,5,5,5,5,
-49,124,5,5,51,51,51,53,5,21,49,5,51,51,51,51,
-43,34,5,5,5,5,5,49,5,21,49,5,21,5,5,5,
-5,49,130,5,52,54,5,49,5,21,49,5,21,5,54,52,
-5,49,5,132,15,50,5,49,5,21,49,5,21,5,49,5
-
-
-
-
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,47,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,47,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,47,0,0
-
-
-
-
-0,0,0,0,0,0,31,0,31,0,0,31,0,31,0,0,
-0,0,31,0,0,30,0,0,0,0,0,0,0,0,0,0,
-0,0,31,23,30,0,0,0,0,0,0,0,0,0,0,23,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,16,30,0,0,0,8,0,0,32,0,0,0,23,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-31,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,8,30,0,0,0,16,0,0,24,0,0,0,23,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,23,30,0,0,0,0,0,0,0,0,31,0,23,
-0,0,31,0,0,0,23,0,0,0,0,0,0,0,0,0,
-0,0,31,0,0,0,29,0,29,0,0,29,0,37,0,0
-
-
-
-
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,71,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,55,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,63,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
-
-
-
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
-
-
diff --git a/assets/Sound/ImpactWall.mp3 b/assets/Sound/ImpactWall.mp3
new file mode 100644
index 00000000..5b92c1c2
Binary files /dev/null and b/assets/Sound/ImpactWall.mp3 differ
diff --git a/assets/Sound/LaserShot.mp3 b/assets/Sound/LaserShot.mp3
new file mode 100644
index 00000000..179795c1
Binary files /dev/null and b/assets/Sound/LaserShot.mp3 differ
diff --git a/assets/Sound/Repair.mp3 b/assets/Sound/Repair.mp3
new file mode 100644
index 00000000..91826746
Binary files /dev/null and b/assets/Sound/Repair.mp3 differ
diff --git a/assets/Sound/WilhelmScream.mp3 b/assets/Sound/WilhelmScream.mp3
new file mode 100644
index 00000000..f3065a5f
Binary files /dev/null and b/assets/Sound/WilhelmScream.mp3 differ
diff --git a/assets/Sound/laser.mp3 b/assets/Sound/laser.mp3
new file mode 100644
index 00000000..06b4115f
Binary files /dev/null and b/assets/Sound/laser.mp3 differ
diff --git a/assets/Sound/menu_music.mp3 b/assets/Sound/menu_music.mp3
new file mode 100644
index 00000000..5f5eb3b9
Binary files /dev/null and b/assets/Sound/menu_music.mp3 differ
diff --git a/assets/Sound/wall_Collision.mp3 b/assets/Sound/wall_Collision.mp3
new file mode 100644
index 00000000..b9f4a54a
Binary files /dev/null and b/assets/Sound/wall_Collision.mp3 differ
diff --git a/assets/images/Exit_Button_Active.png b/assets/images/Exit_Button_Active.png
new file mode 100644
index 00000000..6252df80
Binary files /dev/null and b/assets/images/Exit_Button_Active.png differ
diff --git a/assets/images/Exit_Button_Inactive.png b/assets/images/Exit_Button_Inactive.png
new file mode 100644
index 00000000..41a71772
Binary files /dev/null and b/assets/images/Exit_Button_Inactive.png differ
diff --git a/assets/images/GUI_Edited.jpg b/assets/images/GUI_Edited.jpg
new file mode 100644
index 00000000..430a0c1b
Binary files /dev/null and b/assets/images/GUI_Edited.jpg differ
diff --git a/assets/RoboRallyMenuScreen.png b/assets/images/RoboRallyMenuScreen.png
similarity index 100%
rename from assets/RoboRallyMenuScreen.png
rename to assets/images/RoboRallyMenuScreen.png
diff --git a/assets/images/Start_Button.png b/assets/images/Start_Button.png
new file mode 100644
index 00000000..290a1e58
Binary files /dev/null and b/assets/images/Start_Button.png differ
diff --git a/assets/images/Start_Button_Active.png b/assets/images/Start_Button_Active.png
new file mode 100644
index 00000000..d2148be7
Binary files /dev/null and b/assets/images/Start_Button_Active.png differ
diff --git a/assets/images/YouWin.png b/assets/images/YouWin.png
new file mode 100644
index 00000000..c2f7385c
Binary files /dev/null and b/assets/images/YouWin.png differ
diff --git a/assets/images/damageToken.png b/assets/images/damageToken.png
new file mode 100644
index 00000000..d73d1dd4
Binary files /dev/null and b/assets/images/damageToken.png differ
diff --git a/assets/images/lifeToken.png b/assets/images/lifeToken.png
new file mode 100644
index 00000000..2d470216
Binary files /dev/null and b/assets/images/lifeToken.png differ
diff --git a/assets/images/optimusBoi.gif b/assets/images/optimusBoi.gif
new file mode 100644
index 00000000..66b0cf60
Binary files /dev/null and b/assets/images/optimusBoi.gif differ
diff --git a/assets/maps/Dizzy_Dash.tmx b/assets/maps/Dizzy_Dash.tmx
new file mode 100644
index 00000000..e9b1eff7
--- /dev/null
+++ b/assets/maps/Dizzy_Dash.tmx
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+ 5,50,5,131,5,5,5,5,5,5,5,5,5,5,5,5,
+ 5,50,129,5,5,19,14,14,20,5,5,19,14,14,20,5,
+ 33,44,5,5,5,13,5,54,21,53,5,13,15,54,21,5,
+ 50,123,5,5,5,13,54,7,21,5,5,13,54,5,21,5,
+ 50,5,5,5,5,27,22,22,28,5,53,27,22,22,28,5,
+ 121,5,5,5,5,5,5,5,53,5,5,5,5,53,5,5,
+ 122,5,5,5,5,5,53,5,5,5,5,53,5,5,5,5,
+ 49,5,5,5,5,19,14,14,20,53,5,19,14,14,20,5,
+ 49,124,5,5,5,13,5,54,21,5,5,13,7,54,21,5,
+ 43,34,5,5,5,13,54,15,21,5,53,13,54,5,21,5,
+ 5,49,130,5,5,27,22,22,28,5,5,27,22,22,28,5,
+ 5,49,5,132,5,5,5,5,5,5,5,5,5,5,5,5
+
+
+
+
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+
+
+
+ 0,0,0,0,0,0,31,0,31,0,0,31,0,31,0,0,
+ 0,0,31,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,31,23,30,0,0,0,0,0,0,0,0,0,0,23,
+ 0,0,0,0,0,0,0,0,0,38,0,0,0,30,0,0,
+ 0,0,0,16,30,0,0,0,0,0,0,0,0,0,0,23,
+ 0,0,0,0,0,0,0,31,0,0,0,0,45,0,0,0,
+ 31,31,0,0,0,0,0,37,0,0,0,0,29,0,0,0,
+ 0,0,0,8,30,0,0,0,0,0,0,0,0,0,0,23,
+ 0,0,0,0,0,0,23,0,0,0,46,0,0,0,0,0,
+ 0,0,29,23,30,0,0,0,0,0,0,0,0,0,0,23,
+ 0,0,29,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,29,0,29,0,0,29,0,29,0,0
+
+
+
+
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,71,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,55,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,63,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+
+
+
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+
+
diff --git a/assets/Island_Hop.tmx b/assets/maps/Island_Hop.tmx
similarity index 81%
rename from assets/Island_Hop.tmx
rename to assets/maps/Island_Hop.tmx
index 3ad54a39..b9777a45 100644
--- a/assets/Island_Hop.tmx
+++ b/assets/maps/Island_Hop.tmx
@@ -1,17 +1,18 @@
-
+
-
+
-5,131,5,5,15,5,5,5,5,5,5,5,5,5,5,5,
-5,129,5,5,5,105,109,5,5,5,5,5,5,117,107,5,
-5,5,5,5,5,110,54,52,52,52,52,52,52,52,110,5,
-5,123,5,5,5,5,49,53,51,51,60,51,53,50,5,5,
-5,5,5,5,5,5,49,50,105,109,49,5,49,50,5,5,
-5,121,5,5,5,5,49,50,110,7,49,5,49,50,5,5,
-5,122,5,5,5,5,49,50,5,50,5,118,49,50,5,5,
-5,5,5,5,5,5,49,50,5,50,117,115,49,50,5,5,
+ 5,131,5,5,15,5,5,5,5,5,5,5,5,5,5,5,
+ 5,129,5,5,5,105,109,5,5,5,5,5,5,117,107,5,
+ 5,5,5,5,5,110,54,52,52,52,52,52,52,52,110,5,
+ 5,123,5,5,5,5,49,53,51,51,60,51,53,50,5,5,
+ 5,5,5,5,5,5,49,50,105,109,49,5,49,50,5,5,
+ 5,121,5,5,5,5,49,50,110,7,49,5,49,50,5,5,
+ 5,122,5,5,5,5,49,50,5,50,5,118,49,50,5,5,
+ 5,5,5,5,5,5,49,50,5,50,117,115,49,50,5,5,
5,124,5,5,5,5,49,53,52,58,52,52,53,50,5,5,
5,5,5,5,5,118,54,51,51,51,51,51,51,50,118,5,
5,130,5,5,5,113,109,5,5,5,5,5,5,117,115,5,
diff --git a/assets/maps/Risky_Exchange.tmx b/assets/maps/Risky_Exchange.tmx
new file mode 100644
index 00000000..84620ae2
--- /dev/null
+++ b/assets/maps/Risky_Exchange.tmx
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+ 5,50,5,131,5,6,5,49,5,5,49,5,50,5,49,15,
+ 5,50,129,5,5,5,5,49,5,50,49,5,50,5,5,5,
+ 33,44,5,5,5,5,5,49,5,50,49,5,50,5,5,5,
+ 50,123,5,5,52,52,52,53,5,50,49,5,53,52,52,52,
+ 50,5,5,5,5,5,5,5,5,50,49,5,5,5,5,5,
+ 121,5,5,5,22,22,22,22,22,5,5,51,51,51,51,51,
+ 122,5,5,5,5,52,52,52,52,5,5,52,52,52,52,52,
+ 49,5,5,5,5,5,5,5,7,21,49,5,5,5,5,5,
+ 49,124,5,5,51,51,51,53,5,21,49,5,51,51,51,51,
+ 43,34,5,5,5,5,5,49,5,21,49,5,21,5,5,5,
+ 5,49,130,5,52,54,5,49,5,21,49,5,21,5,54,52,
+ 5,49,5,132,15,50,5,49,5,21,49,5,21,5,49,5
+
+
+
+
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+
+
+
+ 0,0,0,0,0,0,31,0,31,0,0,31,0,31,0,0,
+ 0,0,31,0,0,30,0,0,0,0,0,0,0,0,0,0,
+ 0,0,31,23,30,0,0,0,0,0,0,0,0,0,0,23,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,16,30,0,0,0,8,0,0,32,0,0,0,23,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+31,31,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,8,30,0,0,0,16,0,0,24,0,0,0,23,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,23,30,0,0,0,0,0,0,0,0,31,0,23,
+0,0,31,0,0,0,23,0,0,0,0,0,0,0,0,0,
+0,0,31,0,0,0,29,0,29,0,0,29,0,37,0,0
+
+
+
+
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,71,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,55,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,63,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+
+
+
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
+
+
diff --git a/assets/maps/robots.png b/assets/maps/robots.png
new file mode 100644
index 00000000..dc5d9547
Binary files /dev/null and b/assets/maps/robots.png differ
diff --git a/assets/maps/robots.tsx b/assets/maps/robots.tsx
new file mode 100644
index 00000000..c1e12459
--- /dev/null
+++ b/assets/maps/robots.tsx
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/assets/tiles.png b/assets/maps/tiles.png
similarity index 100%
rename from assets/tiles.png
rename to assets/maps/tiles.png
diff --git a/assets/tiles.tsx b/assets/maps/tiles.tsx
similarity index 100%
rename from assets/tiles.tsx
rename to assets/maps/tiles.tsx
diff --git a/assets/player.png b/assets/player.png
deleted file mode 100644
index dc3b2739..00000000
Binary files a/assets/player.png and /dev/null differ
diff --git a/assets/player.tsx b/assets/player.tsx
deleted file mode 100644
index 97b07778..00000000
--- a/assets/player.tsx
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
diff --git a/assets/programCards/Again.png b/assets/programCards/Again.png
new file mode 100644
index 00000000..32ab0ecb
Binary files /dev/null and b/assets/programCards/Again.png differ
diff --git a/assets/programCards/BackUp.png b/assets/programCards/BackUp.png
new file mode 100644
index 00000000..2e288812
Binary files /dev/null and b/assets/programCards/BackUp.png differ
diff --git a/assets/programCards/EnergyRoutine.png b/assets/programCards/EnergyRoutine.png
new file mode 100644
index 00000000..ac292014
Binary files /dev/null and b/assets/programCards/EnergyRoutine.png differ
diff --git a/assets/programCards/LeftTurn.png b/assets/programCards/LeftTurn.png
new file mode 100644
index 00000000..35d2edea
Binary files /dev/null and b/assets/programCards/LeftTurn.png differ
diff --git a/assets/programCards/Move1.png b/assets/programCards/Move1.png
new file mode 100644
index 00000000..e224d005
Binary files /dev/null and b/assets/programCards/Move1.png differ
diff --git a/assets/programCards/Move2.png b/assets/programCards/Move2.png
new file mode 100644
index 00000000..ec6ce680
Binary files /dev/null and b/assets/programCards/Move2.png differ
diff --git a/assets/programCards/Move3.png b/assets/programCards/Move3.png
new file mode 100644
index 00000000..c8a94b10
Binary files /dev/null and b/assets/programCards/Move3.png differ
diff --git a/assets/programCards/RightTurn.png b/assets/programCards/RightTurn.png
new file mode 100644
index 00000000..f56d74f8
Binary files /dev/null and b/assets/programCards/RightTurn.png differ
diff --git a/assets/programCards/SpeedRoutine.png b/assets/programCards/SpeedRoutine.png
new file mode 100644
index 00000000..4a91af47
Binary files /dev/null and b/assets/programCards/SpeedRoutine.png differ
diff --git a/assets/programCards/U-Turn.png b/assets/programCards/U-Turn.png
new file mode 100644
index 00000000..e5282744
Binary files /dev/null and b/assets/programCards/U-Turn.png differ
diff --git a/assets/skins/default.fnt b/assets/skins/default.fnt
new file mode 100644
index 00000000..37e58940
--- /dev/null
+++ b/assets/skins/default.fnt
@@ -0,0 +1,101 @@
+info face="Droid Sans" size=17 bold=0 italic=0 charset="" unicode=0 stretchH=100 smooth=1 aa=1 padding=0,0,0,0 spacing=1,1
+common lineHeight=20 base=18 scaleW=256 scaleH=128 pages=1 packed=0
+page id=0 file="default.png"
+chars count=95
+char id=32 x=0 y=0 width=0 height=0 xoffset=0 yoffset=16 xadvance=4 page=0 chnl=0
+char id=124 x=0 y=0 width=6 height=20 xoffset=1 yoffset=3 xadvance=9 page=0 chnl=0
+char id=106 x=6 y=0 width=9 height=20 xoffset=-4 yoffset=3 xadvance=4 page=0 chnl=0
+char id=81 x=15 y=0 width=15 height=19 xoffset=-2 yoffset=3 xadvance=12 page=0 chnl=0
+char id=74 x=30 y=0 width=11 height=19 xoffset=-5 yoffset=3 xadvance=4 page=0 chnl=0
+char id=125 x=41 y=0 width=10 height=18 xoffset=-3 yoffset=3 xadvance=6 page=0 chnl=0
+char id=123 x=51 y=0 width=10 height=18 xoffset=-3 yoffset=3 xadvance=6 page=0 chnl=0
+char id=93 x=61 y=0 width=8 height=18 xoffset=-3 yoffset=3 xadvance=5 page=0 chnl=0
+char id=91 x=69 y=0 width=8 height=18 xoffset=-2 yoffset=3 xadvance=5 page=0 chnl=0
+char id=41 x=77 y=0 width=9 height=18 xoffset=-3 yoffset=3 xadvance=5 page=0 chnl=0
+char id=40 x=86 y=0 width=9 height=18 xoffset=-3 yoffset=3 xadvance=5 page=0 chnl=0
+char id=64 x=95 y=0 width=18 height=17 xoffset=-3 yoffset=3 xadvance=14 page=0 chnl=0
+char id=121 x=113 y=0 width=13 height=17 xoffset=-3 yoffset=6 xadvance=8 page=0 chnl=0
+char id=113 x=126 y=0 width=13 height=17 xoffset=-3 yoffset=6 xadvance=9 page=0 chnl=0
+char id=112 x=139 y=0 width=13 height=17 xoffset=-2 yoffset=6 xadvance=9 page=0 chnl=0
+char id=103 x=152 y=0 width=13 height=17 xoffset=-3 yoffset=6 xadvance=8 page=0 chnl=0
+char id=38 x=165 y=0 width=16 height=16 xoffset=-3 yoffset=3 xadvance=11 page=0 chnl=0
+char id=37 x=181 y=0 width=18 height=16 xoffset=-3 yoffset=3 xadvance=14 page=0 chnl=0
+char id=36 x=199 y=0 width=12 height=16 xoffset=-2 yoffset=3 xadvance=9 page=0 chnl=0
+char id=63 x=211 y=0 width=11 height=16 xoffset=-3 yoffset=3 xadvance=7 page=0 chnl=0
+char id=33 x=222 y=0 width=7 height=16 xoffset=-2 yoffset=3 xadvance=4 page=0 chnl=0
+char id=48 x=229 y=0 width=13 height=16 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0
+char id=57 x=242 y=0 width=13 height=16 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0
+char id=56 x=0 y=20 width=13 height=16 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0
+char id=54 x=13 y=20 width=13 height=16 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0
+char id=53 x=26 y=20 width=12 height=16 xoffset=-2 yoffset=3 xadvance=9 page=0 chnl=0
+char id=51 x=38 y=20 width=13 height=16 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0
+char id=100 x=51 y=20 width=13 height=16 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0
+char id=98 x=64 y=20 width=13 height=16 xoffset=-2 yoffset=3 xadvance=9 page=0 chnl=0
+char id=85 x=77 y=20 width=14 height=16 xoffset=-2 yoffset=3 xadvance=11 page=0 chnl=0
+char id=83 x=91 y=20 width=13 height=16 xoffset=-3 yoffset=3 xadvance=8 page=0 chnl=0
+char id=79 x=104 y=20 width=15 height=16 xoffset=-2 yoffset=3 xadvance=12 page=0 chnl=0
+char id=71 x=119 y=20 width=14 height=16 xoffset=-2 yoffset=3 xadvance=11 page=0 chnl=0
+char id=67 x=133 y=20 width=13 height=16 xoffset=-2 yoffset=3 xadvance=10 page=0 chnl=0
+char id=127 x=146 y=20 width=12 height=15 xoffset=-2 yoffset=3 xadvance=10 page=0 chnl=0
+char id=35 x=158 y=20 width=15 height=15 xoffset=-3 yoffset=3 xadvance=10 page=0 chnl=0
+char id=92 x=173 y=20 width=11 height=15 xoffset=-3 yoffset=3 xadvance=6 page=0 chnl=0
+char id=47 x=184 y=20 width=11 height=15 xoffset=-3 yoffset=3 xadvance=6 page=0 chnl=0
+char id=59 x=195 y=20 width=8 height=15 xoffset=-3 yoffset=6 xadvance=4 page=0 chnl=0
+char id=55 x=203 y=20 width=13 height=15 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0
+char id=52 x=216 y=20 width=14 height=15 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0
+char id=50 x=230 y=20 width=13 height=15 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0
+char id=49 x=243 y=20 width=9 height=15 xoffset=-2 yoffset=3 xadvance=9 page=0 chnl=0
+char id=116 x=0 y=36 width=10 height=15 xoffset=-3 yoffset=4 xadvance=5 page=0 chnl=0
+char id=108 x=10 y=36 width=6 height=15 xoffset=-2 yoffset=3 xadvance=4 page=0 chnl=0
+char id=107 x=16 y=36 width=12 height=15 xoffset=-2 yoffset=3 xadvance=8 page=0 chnl=0
+char id=105 x=28 y=36 width=7 height=15 xoffset=-2 yoffset=3 xadvance=4 page=0 chnl=0
+char id=104 x=35 y=36 width=12 height=15 xoffset=-2 yoffset=3 xadvance=10 page=0 chnl=0
+char id=102 x=47 y=36 width=11 height=15 xoffset=-3 yoffset=3 xadvance=5 page=0 chnl=0
+char id=90 x=58 y=36 width=13 height=15 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0
+char id=89 x=71 y=36 width=13 height=15 xoffset=-3 yoffset=3 xadvance=8 page=0 chnl=0
+char id=88 x=84 y=36 width=14 height=15 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0
+char id=87 x=98 y=36 width=19 height=15 xoffset=-3 yoffset=3 xadvance=15 page=0 chnl=0
+char id=86 x=117 y=36 width=14 height=15 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0
+char id=84 x=131 y=36 width=13 height=15 xoffset=-3 yoffset=3 xadvance=8 page=0 chnl=0
+char id=82 x=144 y=36 width=13 height=15 xoffset=-2 yoffset=3 xadvance=10 page=0 chnl=0
+char id=80 x=157 y=36 width=12 height=15 xoffset=-2 yoffset=3 xadvance=9 page=0 chnl=0
+char id=78 x=169 y=36 width=14 height=15 xoffset=-2 yoffset=3 xadvance=12 page=0 chnl=0
+char id=77 x=183 y=36 width=17 height=15 xoffset=-2 yoffset=3 xadvance=14 page=0 chnl=0
+char id=76 x=200 y=36 width=11 height=15 xoffset=-2 yoffset=3 xadvance=8 page=0 chnl=0
+char id=75 x=211 y=36 width=13 height=15 xoffset=-2 yoffset=3 xadvance=9 page=0 chnl=0
+char id=73 x=224 y=36 width=10 height=15 xoffset=-3 yoffset=3 xadvance=5 page=0 chnl=0
+char id=72 x=234 y=36 width=14 height=15 xoffset=-2 yoffset=3 xadvance=11 page=0 chnl=0
+char id=70 x=0 y=51 width=11 height=15 xoffset=-2 yoffset=3 xadvance=8 page=0 chnl=0
+char id=69 x=11 y=51 width=11 height=15 xoffset=-2 yoffset=3 xadvance=8 page=0 chnl=0
+char id=68 x=22 y=51 width=14 height=15 xoffset=-2 yoffset=3 xadvance=11 page=0 chnl=0
+char id=66 x=36 y=51 width=13 height=15 xoffset=-2 yoffset=3 xadvance=10 page=0 chnl=0
+char id=65 x=49 y=51 width=15 height=15 xoffset=-3 yoffset=3 xadvance=10 page=0 chnl=0
+char id=58 x=64 y=51 width=7 height=13 xoffset=-2 yoffset=6 xadvance=4 page=0 chnl=0
+char id=117 x=71 y=51 width=12 height=13 xoffset=-2 yoffset=6 xadvance=10 page=0 chnl=0
+char id=115 x=83 y=51 width=11 height=13 xoffset=-3 yoffset=6 xadvance=7 page=0 chnl=0
+char id=111 x=94 y=51 width=13 height=13 xoffset=-3 yoffset=6 xadvance=9 page=0 chnl=0
+char id=101 x=107 y=51 width=13 height=13 xoffset=-3 yoffset=6 xadvance=9 page=0 chnl=0
+char id=99 x=120 y=51 width=12 height=13 xoffset=-3 yoffset=6 xadvance=7 page=0 chnl=0
+char id=97 x=132 y=51 width=12 height=13 xoffset=-3 yoffset=6 xadvance=9 page=0 chnl=0
+char id=60 x=144 y=51 width=13 height=12 xoffset=-3 yoffset=5 xadvance=9 page=0 chnl=0
+char id=122 x=157 y=51 width=11 height=12 xoffset=-3 yoffset=6 xadvance=7 page=0 chnl=0
+char id=120 x=168 y=51 width=13 height=12 xoffset=-3 yoffset=6 xadvance=8 page=0 chnl=0
+char id=119 x=181 y=51 width=17 height=12 xoffset=-3 yoffset=6 xadvance=12 page=0 chnl=0
+char id=118 x=198 y=51 width=13 height=12 xoffset=-3 yoffset=6 xadvance=8 page=0 chnl=0
+char id=114 x=211 y=51 width=10 height=12 xoffset=-2 yoffset=6 xadvance=6 page=0 chnl=0
+char id=110 x=221 y=51 width=12 height=12 xoffset=-2 yoffset=6 xadvance=10 page=0 chnl=0
+char id=109 x=233 y=51 width=17 height=12 xoffset=-2 yoffset=6 xadvance=15 page=0 chnl=0
+char id=94 x=0 y=66 width=13 height=11 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0
+char id=62 x=13 y=66 width=13 height=11 xoffset=-3 yoffset=5 xadvance=9 page=0 chnl=0
+char id=42 x=26 y=66 width=13 height=10 xoffset=-3 yoffset=3 xadvance=9 page=0 chnl=0
+char id=43 x=39 y=66 width=13 height=10 xoffset=-3 yoffset=6 xadvance=9 page=0 chnl=0
+char id=61 x=52 y=66 width=13 height=8 xoffset=-3 yoffset=7 xadvance=9 page=0 chnl=0
+char id=39 x=65 y=66 width=6 height=8 xoffset=-2 yoffset=3 xadvance=3 page=0 chnl=0
+char id=34 x=71 y=66 width=9 height=8 xoffset=-2 yoffset=3 xadvance=6 page=0 chnl=0
+char id=44 x=80 y=66 width=8 height=7 xoffset=-3 yoffset=14 xadvance=4 page=0 chnl=0
+char id=126 x=88 y=66 width=13 height=6 xoffset=-3 yoffset=8 xadvance=9 page=0 chnl=0
+char id=46 x=101 y=66 width=7 height=6 xoffset=-2 yoffset=13 xadvance=4 page=0 chnl=0
+char id=96 x=108 y=66 width=8 height=6 xoffset=0 yoffset=2 xadvance=9 page=0 chnl=0
+char id=45 x=116 y=66 width=9 height=5 xoffset=-3 yoffset=10 xadvance=5 page=0 chnl=0
+char id=95 x=125 y=66 width=13 height=4 xoffset=-4 yoffset=17 xadvance=6 page=0 chnl=0
+kernings count=-1
diff --git a/assets/skins/default.png b/assets/skins/default.png
new file mode 100644
index 00000000..ca368e07
Binary files /dev/null and b/assets/skins/default.png differ
diff --git a/assets/skins/default_00.png b/assets/skins/default_00.png
new file mode 100644
index 00000000..94ce570f
Binary files /dev/null and b/assets/skins/default_00.png differ
diff --git a/assets/skins/uiskin.atlas b/assets/skins/uiskin.atlas
new file mode 100644
index 00000000..c1935816
--- /dev/null
+++ b/assets/skins/uiskin.atlas
@@ -0,0 +1,198 @@
+
+uiskin.png
+format: RGBA8888
+filter: Nearest,Nearest
+repeat: none
+default
+ rotate: false
+ xy: 1, 50
+ size: 254, 77
+ orig: 254, 77
+ offset: 0, 0
+ index: -1
+default-window
+ rotate: false
+ xy: 1, 20
+ size: 27, 29
+ split: 4, 3, 20, 3
+ orig: 27, 29
+ offset: 0, 0
+ index: -1
+default-select
+ rotate: false
+ xy: 29, 29
+ size: 27, 20
+ split: 4, 14, 4, 4
+ orig: 27, 20
+ offset: 0, 0
+ index: -1
+default-round-large
+ rotate: false
+ xy: 57, 29
+ size: 20, 20
+ split: 5, 5, 5, 4
+ orig: 20, 20
+ offset: 0, 0
+ index: -1
+default-scroll
+ rotate: false
+ xy: 78, 29
+ size: 20, 20
+ split: 2, 2, 2, 2
+ orig: 20, 20
+ offset: 0, 0
+ index: -1
+default-slider-knob
+ rotate: false
+ xy: 1, 1
+ size: 9, 18
+ orig: 9, 18
+ offset: 0, 0
+ index: -1
+default-round-down
+ rotate: false
+ xy: 99, 29
+ size: 12, 20
+ split: 5, 5, 5, 4
+ orig: 12, 20
+ offset: 0, 0
+ index: -1
+default-round
+ rotate: false
+ xy: 112, 29
+ size: 12, 20
+ split: 5, 5, 5, 4
+ pad: 4, 4, 1, 1
+ orig: 12, 20
+ offset: 0, 0
+ index: -1
+check-off
+ rotate: false
+ xy: 11, 5
+ size: 14, 14
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+textfield
+ rotate: false
+ xy: 11, 5
+ size: 14, 14
+ split: 3, 3, 3, 3
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+check-on
+ rotate: false
+ xy: 125, 35
+ size: 14, 14
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+tree-minus
+ rotate: false
+ xy: 140, 35
+ size: 14, 14
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+tree-plus
+ rotate: false
+ xy: 155, 35
+ size: 14, 14
+ orig: 14, 14
+ offset: 0, 0
+ index: -1
+default-slider
+ rotate: false
+ xy: 29, 20
+ size: 8, 8
+ split: 2, 2, 2, 2
+ orig: 8, 8
+ offset: 0, 0
+ index: -1
+default-pane
+ rotate: false
+ xy: 11, 1
+ size: 5, 3
+ split: 1, 1, 1, 1
+ orig: 5, 3
+ offset: 0, 0
+ index: -1
+default-rect-pad
+ rotate: false
+ xy: 11, 1
+ size: 5, 3
+ split: 1, 1, 1, 1
+ orig: 5, 3
+ offset: 0, 0
+ index: -1
+default-splitpane
+ rotate: false
+ xy: 17, 1
+ size: 5, 3
+ split: 0, 5, 0, 0
+ orig: 5, 3
+ offset: 0, 0
+ index: -1
+cursor
+ rotate: false
+ xy: 23, 1
+ size: 3, 3
+ split: 1, 1, 1, 1
+ orig: 3, 3
+ offset: 0, 0
+ index: -1
+default-splitpane-vertical
+ rotate: false
+ xy: 125, 29
+ size: 3, 5
+ split: 0, 0, 0, 5
+ orig: 3, 5
+ offset: 0, 0
+ index: -1
+default-rect-down
+ rotate: false
+ xy: 170, 46
+ size: 3, 3
+ split: 1, 1, 1, 1
+ orig: 3, 3
+ offset: 0, 0
+ index: -1
+default-rect
+ rotate: false
+ xy: 38, 25
+ size: 3, 3
+ split: 1, 1, 1, 1
+ orig: 3, 3
+ offset: 0, 0
+ index: -1
+default-select-selection
+ rotate: false
+ xy: 26, 16
+ size: 3, 3
+ split: 1, 1, 1, 1
+ orig: 3, 3
+ offset: 0, 0
+ index: -1
+default-pane-noborder
+ rotate: false
+ xy: 129, 33
+ size: 1, 1
+ split: 0, 0, 0, 0
+ orig: 1, 1
+ offset: 0, 0
+ index: -1
+selection
+ rotate: false
+ xy: 170, 44
+ size: 1, 1
+ orig: 1, 1
+ offset: 0, 0
+ index: -1
+white
+ rotate: false
+ xy: 174, 48
+ size: 1, 1
+ orig: 1, 1
+ offset: 0, 0
+ index: -1
diff --git a/assets/skins/uiskin.json b/assets/skins/uiskin.json
new file mode 100644
index 00000000..e4d24292
--- /dev/null
+++ b/assets/skins/uiskin.json
@@ -0,0 +1,58 @@
+{
+ "com.badlogic.gdx.graphics.g2d.BitmapFont": { "default-font": { "file": "default.fnt" } },
+ "com.badlogic.gdx.graphics.Color": {
+ "green": { "a": 1, "b": 0, "g": 1, "r": 0 },
+ "white": { "a": 1, "b": 1, "g": 1, "r": 1 },
+ "red": { "a": 1, "b": 0, "g": 0, "r": 1 },
+ "black": { "a": 1, "b": 0, "g": 0, "r": 0 }
+ },
+ "com.badlogic.gdx.scenes.scene2d.ui.Skin$TintedDrawable": {
+ "dialogDim": { "name": "white", "color": { "r": 0, "g": 0, "b": 0, "a": 0.45 } }
+ },
+ "com.badlogic.gdx.scenes.scene2d.ui.Button$ButtonStyle": {
+ "default": { "down": "default-round-down", "up": "default-round" },
+ "toggle": { "down": "default-round-down", "checked": "default-round-down", "up": "default-round" }
+ },
+ "com.badlogic.gdx.scenes.scene2d.ui.TextButton$TextButtonStyle": {
+ "default": { "down": "default-round-down", "up": "default-round", "font": "default-font", "fontColor": "white" },
+ "toggle": { "down": "default-round-down", "up": "default-round", "checked": "default-round-down", "font": "default-font", "fontColor": "white", "downFontColor": "red" }
+ },
+ "com.badlogic.gdx.scenes.scene2d.ui.SelectBox$SelectBoxStyle": {
+ "default": {
+ "scrollStyle": { "background": "default-rect" },
+ "listStyle": { "font": "default-font", "selection": "default-select-selection" },
+ "font": "default-font", "fontColor": "white", "background": "default-select" }
+ },
+ "com.badlogic.gdx.scenes.scene2d.ui.SplitPane$SplitPaneStyle": {
+ "default-vertical": { "handle": "default-splitpane-vertical" },
+ "default-horizontal": { "handle": "default-splitpane" }
+ },
+ "com.badlogic.gdx.scenes.scene2d.ui.ScrollPane$ScrollPaneStyle": {
+ "default": { "vScroll": "default-scroll", "hScrollKnob": "default-round-large", "background": "default-rect", "hScroll": "default-scroll", "vScrollKnob": "default-round-large" }
+ },
+ "com.badlogic.gdx.scenes.scene2d.ui.Window$WindowStyle": {
+ "default": { "titleFont": "default-font", "background": "default-window", "titleFontColor": "white" },
+ "dialog": { "titleFont": "default-font", "background": "default-window", "titleFontColor": "white", "stageBackground": "dialogDim" }
+ },
+ "com.badlogic.gdx.scenes.scene2d.ui.Slider$SliderStyle": {
+ "default-horizontal": { "background": "default-slider", "knob": "default-slider-knob" }
+ },
+ "com.badlogic.gdx.scenes.scene2d.ui.Label$LabelStyle": {
+ "default": { "font": "default-font", "fontColor": "white" }
+ },
+ "com.badlogic.gdx.scenes.scene2d.ui.TextField$TextFieldStyle": {
+ "default": { "selection": "selection", "background": "textfield", "font": "default-font", "fontColor": "white", "cursor": "cursor" }
+ },
+ "com.badlogic.gdx.scenes.scene2d.ui.CheckBox$CheckBoxStyle": {
+ "default": { "checkboxOn": "check-on", "checkboxOff": "check-off", "font": "default-font", "fontColor": "white" }
+ },
+ "com.badlogic.gdx.scenes.scene2d.ui.List$ListStyle": {
+ "default": { "fontColorUnselected": "white", "selection": "default-rect-pad", "fontColorSelected": "white", "font": "default-font" }
+ },
+ "com.badlogic.gdx.scenes.scene2d.ui.Touchpad$TouchpadStyle": {
+ "default": { "background": "default-pane", "knob": "default-round-large" }
+ },
+ "com.badlogic.gdx.scenes.scene2d.ui.Tree$TreeStyle": {
+ "default": { "minus": "tree-minus", "plus": "tree-plus", "selection": "default-select-selection" }
+ }
+}
diff --git a/assets/skins/uiskin.png b/assets/skins/uiskin.png
new file mode 100644
index 00000000..da012c5e
Binary files /dev/null and b/assets/skins/uiskin.png differ
diff --git a/assets/testMap.tmx b/assets/testMap.tmx
deleted file mode 100644
index 1a00dda2..00000000
--- a/assets/testMap.tmx
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
-
-
-
-5,5,5,5,5,
-19,5,5,5,18,
-13,5,6,5,13,
-13,5,5,5,13,
-121,5,5,5,122
-
-
-
-
-0,0,47,0,0,
-0,0,47,0,0,
-0,0,47,0,0,
-0,0,47,0,0,
-0,0,47,0,0
-
-
-
-
-0,0,31,0,0,
-0,0,0,0,0,
-0,0,0,0,0,
-0,0,0,0,0,
-0,0,37,0,0
-
-
-
-
-55,0,71,0,63,
-0,0,0,0,0,
-0,0,0,0,0,
-0,0,0,0,0,
-0,0,0,0,0
-
-
-
-
-0,0,0,0,0,
-0,0,0,0,0,
-0,0,0,0,0,
-0,0,0,0,0,
-0,0,0,0,0
-
-
-
diff --git a/pom.xml b/pom.xml
index b841e501..e36f4c65 100644
--- a/pom.xml
+++ b/pom.xml
@@ -8,14 +8,14 @@
mvn-app
1.0-SNAPSHOT
- mvn-app
+ RoboRally
- http://www.example.com
+ https://github.com/inf112-v20/error_brain_not_found
UTF-8
- 1.7
- 1.7
+ 1.8
+ 1.8
@@ -107,5 +107,16 @@
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 8
+ 8
+
+
+
diff --git a/src/main/java/inf112/skeleton/app/Board.java b/src/main/java/inf112/skeleton/app/Board.java
index c1e40330..c4adf502 100644
--- a/src/main/java/inf112/skeleton/app/Board.java
+++ b/src/main/java/inf112/skeleton/app/Board.java
@@ -1,6 +1,9 @@
package inf112.skeleton.app;
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.audio.Sound;
import com.badlogic.gdx.maps.tiled.TiledMap;
+import com.badlogic.gdx.maps.tiled.TiledMapTile;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.maps.tiled.TiledMapTileSet;
import com.badlogic.gdx.math.Vector2;
@@ -9,241 +12,560 @@
import inf112.skeleton.app.objects.Flag;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
public class Board extends BoardLayers {
- private final ArrayList flags;
- private ArrayList players;
+ private final ArrayList players;
- public Board() {
- this("assets/testMap.tmx");
- }
+ private final Sound scream = Gdx.audio.newSound(Gdx.files.internal("assets/Sound/WilhelmScream.mp3"));
+ private final Sound wallImpact = Gdx.audio.newSound(Gdx.files.internal("assets/Sound/ImpactWall.mp3"));
- public Board(String mapPath) {
+ public Board(String mapPath, int numberOfPlayers) {
super(mapPath);
this.players = new ArrayList<>();
- this.flags = new ArrayList<>();
- findFlags();
- addPlayersToStartPositions(2);
+
+ addPlayersToStartPositions(numberOfPlayers);
+ }
+
+ private TiledMapTile getRobotTile(Player player) {
+ TiledMapTileSet tileSet = this.tiledMap.getTileSets().getTileSet("robots");
+ switch (player.getDirection()) {
+ case SOUTH:
+ return tileSet.getTile(TileID.PLAYER_SOUTH.getId());
+ case NORTH:
+ return tileSet.getTile(TileID.PLAYER_NORTH.getId());
+ case EAST:
+ return tileSet.getTile(TileID.PLAYER_EAST.getId());
+ case WEST:
+ return tileSet.getTile(TileID.PLAYER_WEST.getId());
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * @param number number of player
+ * @return true if player number is valid
+ */
+ public boolean validPlayerNumber(int number) {
+ for (Player player : players) {
+ if (number == player.getPlayerNr()) {
+ return false;
+ }
+ }
+ return 0 < number && number < 9;
}
/**
- * Finds the where the flags are on the board and makes {@link Flag} objects.
- * And puts them in to the flag array.
+ * Make new player and add player to game and board
+ *
+ * @param x coordinate
+ * @param y coordinate
+ * @param playerNumber of player
+ */
+ public void addPlayer(int x, int y, int playerNumber) {
+ if (!validPlayerNumber(playerNumber)) {
+ return;
+ }
+ Player player = new Player(new Vector2(x, y), playerNumber);
+ addPlayer(player);
+ }
+
+ /**
+ * Add a player to the player layer in coordinate (x, y) and
+ * add that player to the list of players
+ *
+ * @param player to add to game and board
*/
- public void findFlags() {
+ public void addPlayer(Player player) {
+ TiledMapTileLayer.Cell cell = new TiledMapTileLayer.Cell();
+ cell.setTile(getRobotTile(player));
+ playerLayer.setCell((int) player.getPosition().x, (int) player.getPosition().y, cell);
+ if (!players.contains(player)) {
+ players.add(player);
+ }
+ }
+
+ public Vector2 getStartPosition(int number) {
for (int x = 0; x < groundLayer.getWidth(); x++) {
for (int y = 0; y < groundLayer.getHeight(); y++) {
- TiledMapTileLayer.Cell cell = flagLayer.getCell(x, y);
- if (cell != null) {
- int ID = cell.getTile().getId();
- if (ID == 55) {
- flags.add(new Flag(1, x, y));
- } else if (ID == 63) {
- flags.add(new Flag(2, x, y));
- } else if (ID == 71) {
- flags.add(new Flag(3, x, y));
- }
+ TiledMapTileLayer.Cell cell = groundLayer.getCell(x, y);
+ int ID = cell.getTile().getId();
+ if (number == 1 && ID == TileID.START_POS1.getId()) {
+ return new Vector2(x, y);
+ } else if (number == 2 && ID == TileID.START_POS2.getId()) {
+ return new Vector2(x, y);
+ } else if (number == 3 && ID == TileID.START_POS3.getId()) {
+ return new Vector2(x, y);
+ } else if (number == 4 && ID == TileID.START_POS4.getId()) {
+ return new Vector2(x, y);
+ } else if (number == 5 && ID == TileID.START_POS5.getId()) {
+ return new Vector2(x, y);
+ } else if (number == 6 && ID == TileID.START_POS6.getId()) {
+ return new Vector2(x, y);
+ } else if (number == 7 && ID == TileID.START_POS7.getId()) {
+ return new Vector2(x, y);
+ } else if (number == 8 && ID == TileID.START_POS8.getId()) {
+ return new Vector2(x, y);
}
}
}
+ return null;
}
/**
- * Check all cells on map for start positions got by {@link TileID} and add a new player to that
+ * Check all cells on map for start positions with {@link TileID} and add a new player to that
* position based on number of players
*
* @param numPlayers number of robots playing, between 1-8
*/
public void addPlayersToStartPositions(int numPlayers) {
- for (int x = 0; x < groundLayer.getWidth(); x++) {
- for (int y = 0; y < groundLayer.getHeight(); y++) {
- TiledMapTileLayer.Cell cell = groundLayer.getCell(x, y);
- int ID = cell.getTile().getId();
- if (ID == TileID.STARTPOS1.getId()) {
- addPlayer(x, y, 1);
- } else if (ID == TileID.STARTPOS2.getId() && numPlayers > 1) {
- addPlayer(x, y, 2);
- } else if (ID == TileID.STARTPOS3.getId() && numPlayers > 2) {
- addPlayer(x, y, 3);
- } else if (ID == TileID.STARTPOS4.getId() && numPlayers > 3) {
- addPlayer(x, y, 4);
- } else if (ID == TileID.STARTPOS5.getId() && numPlayers > 4) {
- addPlayer(x, y, 5);
- } else if (ID == TileID.STARTPOS6.getId() && numPlayers > 5) {
- addPlayer(x, y, 6);
- } else if (ID == TileID.STARTPOS7.getId() && numPlayers > 6) {
- addPlayer(x, y, 7);
- } else if (ID == TileID.STARTPOS8.getId() && numPlayers > 7) {
- addPlayer(x, y, 8);
- }
+ if (numPlayers == 0) {
+ return;
+ }
+ for (int playerNr = 1; playerNr <= numPlayers; playerNr++) {
+ Vector2 position = getStartPosition(playerNr);
+ addPlayer((int) position.x, (int) position.y, playerNr);
+ }
+ }
+
+ /**
+ * Add laser in position in the right direction
+ *
+ * @param position to add laser
+ * @param direction of laser
+ */
+ public void addLaser(Vector2 position, Direction direction) {
+ TiledMapTileLayer.Cell cell = laserLayer.getCell((int) position.x, (int) position.y);
+ TiledMapTileSet tileSet = tiledMap.getTileSets().getTileSet("tiles");
+ if (cell == null) {
+ cell = new TiledMapTileLayer.Cell();
+ }
+ if (direction == Direction.NORTH || direction == Direction.SOUTH) {
+ if (cell.getTile() == null) {
+ cell.setTile(tileSet.getTile(TileID.VERTICAL_LASER.getId()));
+ } else if (cell.getTile().getId() == TileID.HORIZONTAL_LASER.getId()) {
+ cell.setTile(tileSet.getTile(TileID.CROSSED_LASER.getId()));
+ }
+ } else {
+ if (cell.getTile() == null) {
+ cell.setTile(tileSet.getTile(TileID.HORIZONTAL_LASER.getId()));
+ } else if (cell.getTile().getId() == TileID.VERTICAL_LASER.getId()) {
+ cell.setTile(tileSet.getTile(TileID.CROSSED_LASER.getId()));
+ }
+ }
+ laserLayer.setCell((int) position.x, (int) position.y, cell);
+ }
+
+ /**
+ * Checks if player moves on to a hole
+ *
+ * @param position that is checked
+ * @return true if the position contains a hole
+ */
+ public boolean hasHole(Vector2 position) {
+ for (Vector2 vector : holes) {
+ if (vector.equals(position)) {
+ scream.play();
+ return true;
}
}
+ return false;
}
+ /**
+ * Check if player is outside of board
+ *
+ * @param player to check
+ */
+ public boolean outsideBoard(Player player) {
+ return player.getPosition().x < 0 ||
+ player.getPosition().x >= this.boardWidth ||
+ player.getPosition().y < 0 ||
+ player.getPosition().y >= this.boardHeight ||
+ hasHole(player.getPosition());
+ }
/**
- * Add a player to the player layer in coordinate (x, y) and
- * add that player to the list of players
+ * Places a player in backup position or alternative position
*
- * @param x coordinate
- * @param y coordinate
+ * @param player to respawn
*/
- public void addPlayer(int x, int y, int playerNumber) {
- TiledMapTileLayer.Cell cell = new TiledMapTileLayer.Cell();
- TiledMapTileSet tileSet = tiledMap.getTileSets().getTileSet("player");
- cell.setTile(tileSet.getTile(137));
- playerLayer.setCell(x, y, cell);
- Player player = new Player(new Vector2(x, y), playerNumber);
- players.add(player);
+ public void respawn(Player player) {
+ removePlayerFromBoard(player);
+ if (hasPlayer(player.getBackupPosition())) {
+ player.chooseAlternativeBackupPosition(this, player.getBackupPosition());
+ player.setPosition(new Vector2(player.getAlternativeBackupPosition().x, player.getAlternativeBackupPosition().y));
+ player.setDirection(player.getAlternativeBackupDirection());
+ } else {
+ player.setPosition(new Vector2(player.getBackupPosition().x, player.getBackupPosition().y));
+ player.setDirection(player.getBackupDirection());
+ }
+ addPlayer(player);
+ }
+
+ public void respawnPlayers() {
+ for (Player player : players) {
+ if (outsideBoard(player)) {
+ player.decrementLifeTokens();
+ respawn(player);
+ }
+ }
+ }
+
+ public boolean validRespawnPosition(Vector2 position, Direction direction) {
+ Vector2 currPos = position;
+ for (int step = 0; step < 3; step++) {
+ if (hasPlayer(currPos)) {
+ return false;
+ }
+ currPos = getNeighbourPosition(currPos, direction);
+ }
+ return !hasHole(position);
+ }
+
+ public List getDirectionRandomOrder() {
+ List directions = Arrays.asList(Direction.values());
+ Collections.shuffle(directions);
+ return directions;
}
+ /**
+ * @return player that should be moved with arrows
+ */
public Player getPlayer1() {
for (Player player : players) {
if (player.getPlayerNr() == 1) {
return player;
}
}
- return players.get(0);
+ return null;
}
- public boolean canGo(Player player) {
- Vector2 position = player.getPosition();
- Direction direction = player.getDirection();
+ /**
+ * @param position to go from
+ * @param direction to go in
+ * @return true if there is no wall blocking the way
+ */
+ public boolean canGo(Vector2 position, Direction direction) {
+ TiledMapTileLayer.Cell cell = wallLayer.getCell((int) position.x, (int) position.y);
+ TiledMapTileLayer.Cell northCell = wallLayer.getCell((int) position.x, (int) position.y + 1);
+ TiledMapTileLayer.Cell southCell = wallLayer.getCell((int) position.x, (int) position.y - 1);
+ TiledMapTileLayer.Cell eastCell = wallLayer.getCell((int) position.x + 1, (int) position.y);
+ TiledMapTileLayer.Cell westCell = wallLayer.getCell((int) position.x - 1, (int) position.y);
+
+ switch (direction) {
+ case NORTH:
+ if (hasNorthWall(cell) || hasSouthWall(northCell)) {
+ return false;
+ }
+ break;
+ case SOUTH:
+ if (hasSouthWall(cell) || hasNorthWall(southCell)) {
+ return false;
+ }
+ break;
+ case EAST:
+ if (hasEastWall(cell) || hasWestWall(eastCell)) {
+ return false;
+ }
+ break;
+ case WEST:
+ if (hasWestWall(cell) || hasEastWall(westCell)) {
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+ }
+
+ /**
+ * @param cell to check for wall
+ * @return true if cell has a wall on west side
+ */
+ public boolean hasWestWall(TiledMapTileLayer.Cell cell) {
+ if (cell != null) {
+ int tileID = cell.getTile().getId();
+ return tileID == TileID.WEST_WALL.getId() ||
+ tileID == TileID.NORTHWEST_WALL.getId() ||
+ tileID == TileID.SOUTHWEST_WALL.getId() ||
+ tileID == TileID.WEST_LASER_WALL.getId();
+ }
+ return false;
+ }
+
+ /**
+ * @param cell to check for wall
+ * @return true if cell has a wall on east side
+ */
+ public boolean hasEastWall(TiledMapTileLayer.Cell cell) {
+ if (cell != null) {
+ int tileID = cell.getTile().getId();
+ return tileID == TileID.EAST_WALL.getId() ||
+ tileID == TileID.NORTHEAST_WALL.getId() ||
+ tileID == TileID.SOUTHEAST_WALL.getId() ||
+ tileID == TileID.EAST_LASER_WALL.getId();
+ }
+ return false;
+ }
+
+ /**
+ * @param cell to check for wall
+ * @return true if cell has a wall on south side
+ */
+ public boolean hasSouthWall(TiledMapTileLayer.Cell cell) {
+ if (cell != null) {
+ int tileID = cell.getTile().getId();
+ return tileID == TileID.SOUTH_WALL.getId() ||
+ tileID == TileID.SOUTHWEST_WALL.getId() ||
+ tileID == TileID.SOUTHEAST_WALL.getId() ||
+ tileID == TileID.SOUTH_LASER_WALL.getId();
+ }
+ return false;
+ }
- shouldPush(position, direction);
- if (direction == Direction.EAST) {
- return position.x < boardWidth - 1;
- } else if (direction == Direction.WEST) {
- return position.x > 0;
- } else if (direction == Direction.NORTH) {
- return position.y < boardHeight - 1;
- } else if (direction == Direction.SOUTH) {
- return position.y > 0;
+ /**
+ * @param cell to check for wall
+ * @return true if cell has a wall on north side
+ */
+ public boolean hasNorthWall(TiledMapTileLayer.Cell cell) {
+ if (cell != null) {
+ int tileID = cell.getTile().getId();
+ return tileID == TileID.NORTH_WALL.getId() ||
+ tileID == TileID.NORTHWEST_WALL.getId() ||
+ tileID == TileID.NORTHEAST_WALL.getId() ||
+ tileID == TileID.NORTH_LASER_WALL.getId();
}
return false;
}
+
/**
- * Moves the player from current position one tile in the direction it's facing.
- * Removes the cell its currently on and moves the content of that cell to the cell it moves to.
- * Also updates the fields in player
+ * Add player to the board, so the direction is correct
+ * @param player that should be rotated
+ *
+ */
+ public void rotatePlayer(Player player) {
+ addPlayer(player);
+ }
+
+ /**
+ * Check if it is possible to move in the direction the player are facing.
+ * Check if player should and can push another player, if not return
+ * Remove player from board
+ * Update player position according to direction
+ * Add player to cell that corresponds to player position
*
* @param player that is suppose to move
*/
public void movePlayer(Player player) {
- Vector2 playerPosition = player.getPosition();
- Direction playerDirection = player.getDirection();
+ Vector2 position = player.getPosition();
+ Direction direction = player.getDirection();
- shouldPush(playerPosition, playerDirection);
- switch (playerDirection) {
+ if (!canGo(position, direction)) {
+ wallImpact.play(0.6f);
+ addPlayer(player);
+ return;
+ }
+ if (shouldPush(player)) {
+ Player enemyPlayer = getPlayer(getNeighbourPosition(player.getPosition(), direction));
+ if (canPush(enemyPlayer, direction)) {
+ pushPlayer(enemyPlayer, direction);
+ } else {
+ addPlayer(player);
+ return;
+ }
+ }
+
+ removePlayerFromBoard(player);
+
+ switch (direction) {
case NORTH:
- playerPosition.set(playerPosition.x, playerPosition.y + 1);
+ position.y++;
break;
case EAST:
- playerPosition.set(playerPosition.x + 1, playerPosition.y);
+ position.x++;
break;
case WEST:
- playerPosition.set(playerPosition.x - 1, playerPosition.y);
+ position.x--;
break;
case SOUTH:
- playerPosition.set(playerPosition.x, playerPosition.y - 1);
+ position.y--;
break;
default:
- return;
+ break;
+ }
+
+ player.setPosition(position);
+ addPlayer(player);
+
+ if (hasFlag(player.getPosition())) {
+ pickUpFlag(player);
}
- player.setPosition(playerPosition);
- updatePlayers();
+ }
+
+ public ArrayList getNeighbourhood(Vector2 position) {
+ ArrayList positions = new ArrayList<>();
+ for (int yi = -1; yi <= 1; yi++) {
+ for (int xi = -1; xi <= 1; xi++) {
+ int x = (int) (position.x + xi);
+ int y = (int) (position.y + yi);
+ if (x >= 0 && x < boardWidth && y >= 0 && y < boardHeight) {
+ positions.add(new Vector2(x, y));
+ }
+ }
+ }
+ return positions;
}
/**
- * If player moved outside board, respawn them on last backup location
- * @param player current player
+ * @param position to go from
+ * @param direction to go in
+ * @return neighbour position in direction from position
*/
- private void outsideBoard(Player player) {
- if (player.getPosition().x < 0 || player.getPosition().x > 15 || player.getPosition().y < 0 || player.getPosition().y > 11) {
- player.setPosition(new Vector2(player.getBackupPosition().x, player.getBackupPosition().y));
+ public Vector2 getNeighbourPosition(Vector2 position, Direction direction) {
+ Vector2 neighbourPosition = new Vector2(position);
+ switch (direction) {
+ case EAST:
+ neighbourPosition.x++;
+ break;
+ case WEST:
+ neighbourPosition.x--;
+ break;
+ case NORTH:
+ neighbourPosition.y++;
+ break;
+ case SOUTH:
+ neighbourPosition.y--;
+ break;
+ default:
+ break;
}
+ return neighbourPosition;
+ }
+
+ public boolean hasPlayer(Vector2 position) {
+ for (Player enemyPlayer : players) {
+ if (enemyPlayer.getPosition().equals(position)) {
+ return true;
+ }
+ }
+ return false;
}
/**
- * Check if the moving player should try to push another player
- * @param position of the player that wants to move
- * @param direction of the player that wants to move
+ * Return player if there is a player in that position
+ *
+ * @param position to check
+ * @return player in position
*/
- private void shouldPush(Vector2 position, Direction direction) {
+ public Player getPlayer(Vector2 position) {
for (Player enemyPlayer : players) {
- if (direction == Direction.EAST && enemyPlayer.getPosition().x == position.x + 1 && enemyPlayer.getPosition().y == position.y) {
- pushPlayer(enemyPlayer, direction);
- } else if (direction == Direction.WEST && enemyPlayer.getPosition().x == position.x - 1 && enemyPlayer.getPosition().y == position.y) {
- pushPlayer(enemyPlayer, direction);
- } else if (direction == Direction.NORTH && enemyPlayer.getPosition().x == position.x && enemyPlayer.getPosition().y == position.y + 1) {
- pushPlayer(enemyPlayer, direction);
- } else if (direction == Direction.SOUTH && enemyPlayer.getPosition().x == position.x && enemyPlayer.getPosition().y == position.y - 1) {
- pushPlayer(enemyPlayer, direction);
+ if (enemyPlayer.getPosition().equals(position)) {
+ return enemyPlayer;
}
}
+ return null;
+ }
+
+ /**
+ * Check if the moving player should try to push another player
+ *
+ * @param player trying to move
+ * @return true if player should push another player to move
+ */
+ public boolean shouldPush(Player player) {
+ return hasPlayer(getNeighbourPosition(player.getPosition(), player.getDirection()));
+ }
+
+ /**
+ * @param player that should be pushed
+ * @param direction to push in
+ * @return true if it is possible to push all enemies in a row
+ */
+ private boolean canPush(Player player, Direction direction) {
+ if (hasPlayer(getNeighbourPosition(player.getPosition(), direction))) {
+ return canGo(player.getPosition(), direction) &&
+ canPush(getPlayer(getNeighbourPosition(player.getPosition(), direction)), direction);
+ }
+ return canGo(player.getPosition(), direction);
}
/**
- * @param enemyPlayer enemy player that should be pushed
- * @param direction direction to push enemy player in
+ * Push all players in a row
+ * Remove player from board
+ * Update player position according to direction
+ * Add player to cell that corresponds to player position
+ *
+ * @param player that should be pushed
+ * @param direction to push player in
*/
- private void pushPlayer(Player enemyPlayer, Direction direction) {
+ private void pushPlayer(Player player, Direction direction) {
+ if (hasPlayer(getNeighbourPosition(player.getPosition(), direction))) {
+ pushPlayer(getPlayer(getNeighbourPosition(player.getPosition(), direction)), direction);
+ }
+ removePlayerFromBoard(player);
switch (direction) {
case SOUTH:
- enemyPlayer.setPosition(new Vector2(enemyPlayer.getPosition().x, enemyPlayer.getPosition().y - 1));
+ player.setPosition(new Vector2(player.getPosition().x, player.getPosition().y - 1));
break;
case WEST:
- enemyPlayer.setPosition(new Vector2(enemyPlayer.getPosition().x - 1, enemyPlayer.getPosition().y));
+ player.setPosition(new Vector2(player.getPosition().x - 1, player.getPosition().y));
break;
case EAST:
- enemyPlayer.setPosition(new Vector2(enemyPlayer.getPosition().x + 1, enemyPlayer.getPosition().y));
+ player.setPosition(new Vector2(player.getPosition().x + 1, player.getPosition().y));
break;
case NORTH:
- enemyPlayer.setPosition(new Vector2(enemyPlayer.getPosition().x, enemyPlayer.getPosition().y + 1));
+ player.setPosition(new Vector2(player.getPosition().x, player.getPosition().y + 1));
break;
default:
break;
}
+ addPlayer(player);
}
- //TODO: BUG when you are crashing with a player in the corner. Ist possible to only update the specific tile(?).
- public void updatePlayers() {
- for (int y = 0; y < boardHeight; y++) {
- for (int x = 0; x < boardWidth; x++) {
- playerLayer.setCell(x, y, null);
+ /**
+ * Remove player from board
+ *
+ * @param player to remove from board
+ */
+ public void removePlayerFromBoard(Player player) {
+ playerLayer.setCell((int) player.getPosition().x, (int) player.getPosition().y, null);
+ }
+
+ public boolean hasFlag(Vector2 position) {
+ return flagLayer.getCell((int) position.x, (int) position.y) != null;
+ }
+
+ public Flag getFlag(Vector2 position) {
+ for (Flag flag : flags) {
+ if (flag.getPosition().equals(position)) {
+ return flag;
}
}
- for (Player player : players) {
- TiledMapTileLayer.Cell cell = new TiledMapTileLayer.Cell();
- TiledMapTileSet tileSet = tiledMap.getTileSets().getTileSet("player");
- cell.setTile(tileSet.getTile(137));
- outsideBoard(player);
- playerLayer.setCell((int) player.getPosition().x, (int) player.getPosition().y, cell);
- }
+ return null;
}
- /**
- * @return list of all players
- */
- public ArrayList getPlayers() {
- return players;
+ public void pickUpFlag(Player player) {
+ Flag flag = getFlag(player.getPosition());
+ player.pickUpFlag(getFlag(player.getPosition()), flag.getFlagnr());
}
- /**
- * @return {@link TiledMapTileLayer} of player layer
- */
- public TiledMapTileLayer getPlayerLayer() {
- return playerLayer;
+ public ArrayList getFlags(){
+ return flags;
}
/**
- * @return {@link TiledMapTileLayer} of flag layer
+ * @return list of all players
*/
- public TiledMapTileLayer getFlagLayer() {
- return flagLayer;
+ public ArrayList getPlayers() {
+ return players;
}
/**
@@ -260,13 +582,6 @@ public TiledMapTileLayer getWallLayer() {
return wallLayer;
}
- /**
- * @return {@link TiledMapTileLayer} of ground layer
- */
- public TiledMapTileLayer getGroundLayer() {
- return groundLayer;
- }
-
/**
* @return width of the board
*/
diff --git a/src/main/java/inf112/skeleton/app/BoardLayers.java b/src/main/java/inf112/skeleton/app/BoardLayers.java
index c1732d1f..8ec81bdd 100644
--- a/src/main/java/inf112/skeleton/app/BoardLayers.java
+++ b/src/main/java/inf112/skeleton/app/BoardLayers.java
@@ -4,25 +4,35 @@
import com.badlogic.gdx.maps.tiled.TiledMap;
import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
import com.badlogic.gdx.maps.tiled.TmxMapLoader;
+import com.badlogic.gdx.math.Vector2;
+import inf112.skeleton.app.enums.Direction;
+import inf112.skeleton.app.enums.Rotate;
+import inf112.skeleton.app.enums.TileID;
+import inf112.skeleton.app.objects.Flag;
+import inf112.skeleton.app.objects.Laser;
+import inf112.skeleton.app.objects.RotatePad;
import java.util.ArrayList;
public abstract class BoardLayers {
- public TiledMap tiledMap;
+ public final TiledMap tiledMap;
- public TiledMapTileLayer playerLayer;
- public TiledMapTileLayer flagLayer;
- public TiledMapTileLayer wallLayer;
- public TiledMapTileLayer laserLayer;
- public TiledMapTileLayer groundLayer;
+ public final TiledMapTileLayer playerLayer;
+ public final TiledMapTileLayer flagLayer;
+ public final TiledMapTileLayer wallLayer;
+ public final TiledMapTileLayer laserLayer;
+ public final TiledMapTileLayer groundLayer;
- public int boardWidth;
- public int boardHeight;
+ public final ArrayList lasers;
+ public final ArrayList flags;
+ public final ArrayList rotatePads;
+ public final ArrayList holes;
- private ArrayList players;
+ public final int boardWidth;
+ public final int boardHeight;
- public BoardLayers(String mapPath){
+ public BoardLayers(String mapPath) {
this.tiledMap = new TmxMapLoader().load(mapPath);
this.playerLayer = (TiledMapTileLayer) tiledMap.getLayers().get("Player");
@@ -34,11 +44,109 @@ public BoardLayers(String mapPath){
MapProperties properties = tiledMap.getProperties();
boardWidth = properties.get("width", Integer.class);
boardHeight = properties.get("height", Integer.class);
+
+ this.holes = new ArrayList<>();
+ this.rotatePads = new ArrayList<>();
+ this.flags = new ArrayList<>();
+ this.lasers = new ArrayList<>();
+
+ findFlags();
+ findRotatePadsAndHoles();
+ findLasers();
}
+ /**
+ * Finds where there are {@link RotatePad} and Holes on the map. In the case of RotatePad adds a RotatePad object to
+ * the rotatePad list, in the case of a hole adds a {@link Vector2} to the holes list.
+ */
+ public void findRotatePadsAndHoles() {
+ for (int x = 0; x < groundLayer.getWidth(); x++) {
+ for (int y = 0; y < groundLayer.getHeight(); y++) {
+ TiledMapTileLayer.Cell cell = groundLayer.getCell(x, y);
+ int ID = cell.getTile().getId();
+ if (ID == TileID.NORMAL_HOLE.getId()) {
+ holes.add(new Vector2(x, y));
+ } else if (ID == TileID.NORMAL_HOLE2.getId()) {
+ holes.add(new Vector2(x, y));
+ } else if (ID == TileID.NORTHWEST_HOLE.getId()) {
+ holes.add(new Vector2(x, y));
+ } else if (ID == TileID.NORTH_HOLE.getId()) {
+ holes.add(new Vector2(x, y));
+ } else if (ID == TileID.NORTHEAST_HOLE.getId()) {
+ holes.add(new Vector2(x, y));
+ } else if (ID == TileID.EAST_HOLE.getId()) {
+ holes.add(new Vector2(x, y));
+ } else if (ID == TileID.NORTH_EAST_SOUTH_HOLE.getId()) {
+ holes.add(new Vector2(x, y));
+ } else if (ID == TileID.WEST_EAST_SOUTH_HOLE.getId()) {
+ holes.add(new Vector2(x, y));
+ } else if (ID == TileID.SOUTHWEST_HOLE.getId()) {
+ holes.add(new Vector2(x, y));
+ } else if (ID == TileID.SOUTH_HOLE.getId()) {
+ holes.add(new Vector2(x, y));
+ } else if (ID == TileID.SOUTHEAST_HOLE.getId()) {
+ holes.add(new Vector2(x, y));
+ } else if (ID == TileID.WEST_HOLE.getId()) {
+ holes.add(new Vector2(x, y));
+ } else if (ID == TileID.NORTH_WEST_SOUTH_HOLE.getId()) {
+ holes.add(new Vector2(x, y));
+ } else if (ID == TileID.NORTH_WEST_EAST_HOLE.getId()) {
+ holes.add(new Vector2(x, y));
+ } else if (ID == TileID.ROTATE_PAD_LEFT.getId()) {
+ rotatePads.add(new RotatePad(Rotate.LEFT, new Vector2(x, y)));
+ } else if (ID == TileID.ROTATE_PAD_RIGHT.getId()) {
+ rotatePads.add(new RotatePad(Rotate.RIGHT, new Vector2(x, y)));
+ }
+ }
+ }
+ }
+
+ /**
+ * Finds the where the flags are on the board, makes {@link Flag} objects
+ * and puts them in to the flag array.
+ */
+ public void findFlags() {
+ for (int x = 0; x < flagLayer.getWidth(); x++) {
+ for (int y = 0; y < flagLayer.getHeight(); y++) {
+ TiledMapTileLayer.Cell cell = flagLayer.getCell(x, y);
+ if (cell != null) {
+ int ID = cell.getTile().getId();
+ if (ID == TileID.FLAG_1.getId()) {
+ flags.add(new Flag(1, x, y));
+ } else if (ID == TileID.FLAG_2.getId()) {
+ flags.add(new Flag(2, x, y));
+ } else if (ID == TileID.FLAG_3.getId()) {
+ flags.add(new Flag(3, x, y));
+ } else if (ID == TileID.FLAG_4.getId()) {
+ flags.add(new Flag(4, x, y));
+ }
+ }
+ }
+ }
+ }
+
+ public void findLasers() {
+ for (int x = 0; x < wallLayer.getWidth(); x++) {
+ for (int y = 0; y < wallLayer.getHeight(); y++) {
+ TiledMapTileLayer.Cell cell = wallLayer.getCell(x, y);
+ if (cell != null) {
+ int ID = cell.getTile().getId();
+ if (ID == TileID.EAST_LASER_WALL.getId()) {
+ lasers.add(new Laser(x, y, Direction.WEST));
+ } else if (ID == TileID.WEST_LASER_WALL.getId()) {
+ lasers.add(new Laser(x, y, Direction.EAST));
+ } else if (ID == TileID.NORTH_LASER_WALL.getId()) {
+ lasers.add(new Laser(x, y, Direction.SOUTH));
+ } else if (ID == TileID.SOUTH_LASER_WALL.getId()) {
+ lasers.add(new Laser(x, y, Direction.NORTH));
+ }
+ }
+ }
+ }
+ }
+
public abstract TiledMap getMap();
- public abstract TiledMapTileLayer getPlayerLayer();
- public abstract TiledMapTileLayer getFlagLayer();
+
public abstract TiledMapTileLayer getLaserLayer();
}
diff --git a/src/main/java/inf112/skeleton/app/GifDecoder.java b/src/main/java/inf112/skeleton/app/GifDecoder.java
new file mode 100644
index 00000000..3fa3f8b9
--- /dev/null
+++ b/src/main/java/inf112/skeleton/app/GifDecoder.java
@@ -0,0 +1,738 @@
+package inf112.skeleton.app;
+
+/* Copyright by Johannes Borchardt */
+/* LibGdx conversion 2014 by Anton Persson */
+/* Released under Apache 2.0 */
+/* https://code.google.com/p/animated-gifs-in-android/ */
+
+import com.badlogic.gdx.graphics.Pixmap;
+import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.graphics.g2d.Animation;
+import com.badlogic.gdx.graphics.g2d.Animation.PlayMode;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import com.badlogic.gdx.utils.Array;
+
+import java.io.InputStream;
+import java.util.Vector;
+
+public class GifDecoder {
+ /**
+ * File read status: No errors.
+ */
+ public static final int STATUS_OK = 0;
+ /**
+ * File read status: Error decoding file (may be partially decoded)
+ */
+ public static final int STATUS_FORMAT_ERROR = 1;
+ /**
+ * File read status: Unable to open source.
+ */
+ public static final int STATUS_OPEN_ERROR = 2;
+ /** max decoder pixel stack size */
+ protected static final int MAX_STACK_SIZE = 4096;
+ protected InputStream in;
+ protected int status;
+ protected int width; // full image width
+ protected int height; // full image height
+ protected boolean gctFlag; // global color table used
+ protected int gctSize; // size of global color table
+ protected int loopCount = 1; // iterations; 0 = repeat forever
+ protected int[] gct; // global color table
+ protected int[] lct; // local color table
+ protected int[] act; // active color table
+ protected int bgIndex; // background color index
+ protected int bgColor; // background color
+ protected int lastBgColor; // previous bg color
+ protected int pixelAspect; // pixel aspect ratio
+ protected boolean lctFlag; // local color table flag
+ protected boolean interlace; // interlace flag
+ protected int lctSize; // local color table size
+ protected int ix; // current image rectangle
+ protected int iy; // current image rectangle
+ protected int iw; // current image rectangle
+ protected int ih; // current image rectangle
+ protected int lrx;
+ protected int lry;
+ protected int lrw;
+ protected int lrh;
+ protected DixieMap image; // current frame
+ protected DixieMap lastPixmap; // previous frame
+ protected final byte[] block = new byte[256]; // current data block
+ protected int blockSize = 0; // block size last graphic control extension info
+ protected int dispose = 0; // 0=no action; 1=leave in place; 2=restore to bg; 3=restore to prev
+ protected int lastDispose = 0;
+ protected boolean transparency = false; // use transparent color
+ protected int delay = 0; // delay in milliseconds
+ protected int transIndex; // transparent color index
+ // LZW decoder working arrays
+ protected short[] prefix;
+ protected byte[] suffix;
+ protected byte[] pixelStack;
+ protected byte[] pixels;
+ protected Vector frames; // frames read from current file
+ protected int frameCount;
+
+ /**
+ * Gets the image contents of frame n.
+ *
+ * @return BufferedPixmap representation of frame, or null if n is invalid.
+ */
+ public DixieMap getFrame(int n) {
+ if (frameCount <= 0)
+ return null;
+ n %= frameCount;
+ return frames.elementAt(n).image;
+ }
+
+ /**
+ * Reads GIF image from stream
+ *
+ * @param is containing GIF file.
+ */
+ public void read(InputStream is) {
+ init();
+ if (is != null) {
+ in = is;
+ readHeader();
+ if (!err()) {
+ readContents();
+ if (frameCount < 0) {
+ status = STATUS_FORMAT_ERROR;
+ }
+ }
+ } else {
+ status = STATUS_OPEN_ERROR;
+ }
+ try {
+ assert is != null;
+ is.close();
+ } catch (Exception ignored) {
+ }
+ }
+
+ /**
+ * Gets display duration for specified frame.
+ *
+ * @param n
+ * int index of frame
+ * @return delay in milliseconds
+ */
+ public int getDelay(int n) {
+ delay = -1;
+ if ((n >= 0) && (n < frameCount)) {
+ delay = frames.elementAt(n).delay;
+ }
+ return delay;
+ }
+
+ /**
+ * Gets the number of frames read from file.
+ *
+ * @return frame count
+ */
+ public int getFrameCount() {
+ return frameCount;
+ }
+
+ /**
+ * Creates new frame image from current data (and previous frames as specified by their disposition codes).
+ */
+ protected void setPixels() {
+ // expose destination image's pixels as int array
+ int[] dest = new int[width * height];
+ // fill in starting image contents based on last image's dispose code
+ if (lastDispose > 0) {
+ if (lastDispose == 3) {
+ // use image before last
+ int n = frameCount - 2;
+ if (n > 0) {
+ lastPixmap = getFrame(n - 1);
+ } else {
+ lastPixmap = null;
+ }
+ }
+ if (lastPixmap != null) {
+ lastPixmap.getPixels(dest, 0, width, width, height);
+ // copy pixels
+ if (lastDispose == 2) {
+ // fill last image rect area with background color
+ int c = 0;
+ if (!transparency) {
+ c = lastBgColor;
+ }
+ for (int i = 0; i < lrh; i++) {
+ int n1 = (lry + i) * width + lrx;
+ int n2 = n1 + lrw;
+ for (int k = n1; k < n2; k++) {
+ dest[k] = c;
+ }
+ }
+ }
+ }
+ }
+ // copy each source line to the appropriate place in the destination
+ int pass = 1;
+ int inc = 8;
+ int iline = 0;
+ for (int i = 0; i < ih; i++) {
+ int line = i;
+ if (interlace) {
+ if (iline >= ih) {
+ pass++;
+ switch (pass) {
+ case 2:
+ iline = 4;
+ break;
+ case 3:
+ iline = 2;
+ inc = 4;
+ break;
+ case 4:
+ iline = 1;
+ inc = 2;
+ break;
+ default:
+ break;
+ }
+ }
+ line = iline;
+ iline += inc;
+ }
+ line += iy;
+ if (line < height) {
+ int k = line * width;
+ int dx = k + ix; // start of line in dest
+ int dlim = dx + iw; // end of dest line
+ if ((k + width) < dlim) {
+ dlim = k + width; // past dest edge
+ }
+ int sx = i * iw; // start of line in source
+ while (dx < dlim) {
+ // map color and insert in destination
+ int index = ((int) pixels[sx++]) & 0xff;
+ int c = act[index];
+ if (c != 0) {
+ dest[dx] = c;
+ }
+ dx++;
+ }
+ }
+ }
+ image = new DixieMap(dest, width, height);
+ //Pixmap.createPixmap(dest, width, height, Config.ARGB_4444);
+ }
+
+ /**
+ * Decodes LZW image data into pixel array. Adapted from John Cristy's BitmapMagick.
+ */
+ protected void decodeBitmapData() {
+ int nullCode = -1;
+ int npix = iw * ih;
+ int available;
+ int clear;
+ int code_mask;
+ int code_size;
+ int end_of_information;
+ int in_code;
+ int old_code;
+ int bits;
+ int code;
+ int count;
+ int i;
+ int datum;
+ int data_size;
+ int first;
+ int top;
+ int bi;
+ int pi;
+ if ((pixels == null) || (pixels.length < npix)) {
+ pixels = new byte[npix]; // allocate new pixel array
+ }
+ if (prefix == null) {
+ prefix = new short[MAX_STACK_SIZE];
+ }
+ if (suffix == null) {
+ suffix = new byte[MAX_STACK_SIZE];
+ }
+ if (pixelStack == null) {
+ pixelStack = new byte[MAX_STACK_SIZE + 1];
+ }
+ // Initialize GIF data stream decoder.
+ data_size = read();
+ clear = 1 << data_size;
+ end_of_information = clear + 1;
+ available = clear + 2;
+ old_code = nullCode;
+ code_size = data_size + 1;
+ code_mask = (1 << code_size) - 1;
+ for (code = 0; code < clear; code++) {
+ prefix[code] = 0; // XXX ArrayIndexOutOfBoundsException
+ suffix[code] = (byte) code;
+ }
+ // Decode GIF pixel stream.
+ datum = bits = count = first = top = pi = bi = 0;
+ for (i = 0; i < npix;) {
+ if (top == 0) {
+ if (bits < code_size) {
+ // Load bytes until there are enough bits for a code.
+ if (count == 0) {
+ // Read a new data block.
+ count = readBlock();
+ if (count <= 0) {
+ break;
+ }
+ bi = 0;
+ }
+ datum += (((int) block[bi]) & 0xff) << bits;
+ bits += 8;
+ bi++;
+ count--;
+ continue;
+ }
+ // Get the next code.
+ code = datum & code_mask;
+ datum >>= code_size;
+ bits -= code_size;
+ // Interpret the code
+ if ((code > available) || (code == end_of_information)) {
+ break;
+ }
+ if (code == clear) {
+ // Reset decoder.
+ code_size = data_size + 1;
+ code_mask = (1 << code_size) - 1;
+ available = clear + 2;
+ old_code = nullCode;
+ continue;
+ }
+ if (old_code == nullCode) {
+ pixelStack[top++] = suffix[code];
+ old_code = code;
+ first = code;
+ continue;
+ }
+ in_code = code;
+ if (code == available) {
+ pixelStack[top++] = (byte) first;
+ code = old_code;
+ }
+ while (code > clear) {
+ pixelStack[top++] = suffix[code];
+ code = prefix[code];
+ }
+ first = ((int) suffix[code]) & 0xff;
+ // Add a new string to the string table,
+ if (available >= MAX_STACK_SIZE) {
+ break;
+ }
+ pixelStack[top++] = (byte) first;
+ prefix[available] = (short) old_code;
+ suffix[available] = (byte) first;
+ available++;
+ if (((available & code_mask) == 0) && (available < MAX_STACK_SIZE)) {
+ code_size++;
+ code_mask += available;
+ }
+ old_code = in_code;
+ }
+ // Pop a pixel off the pixel stack.
+ top--;
+ pixels[pi++] = pixelStack[top];
+ i++;
+ }
+ for (i = pi; i < npix; i++) {
+ pixels[i] = 0; // clear missing pixels
+ }
+ }
+
+ /**
+ * Initializes or re-initializes reader
+ */
+ protected void init() {
+ status = STATUS_OK;
+ frameCount = 0;
+ frames = new Vector<>();
+ gct = null;
+ lct = null;
+ }
+
+ /**
+ * Reads next variable length block from input.
+ *
+ * @return number of bytes stored in "buffer"
+ */
+ protected int readBlock() {
+ blockSize = read();
+ int n = 0;
+ if (blockSize > 0) {
+ try {
+ int count;
+ while (n < blockSize) {
+ count = in.read(block, n, blockSize - n);
+ if (count == -1) {
+ break;
+ }
+ n += count;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ if (n < blockSize) {
+ status = STATUS_FORMAT_ERROR;
+ }
+ }
+ return n;
+ }
+
+ /**
+ * Returns true if an error was encountered during reading/decoding
+ */
+ protected boolean err() {
+ return status != STATUS_OK;
+ }
+
+ /**
+ * Main file parser. Reads GIF content blocks.
+ */
+ protected void readContents() {
+ // read GIF file content blocks
+ boolean done = false;
+ while (!(done || err())) {
+ int code = read();
+ switch (code) {
+ case 0x2C: // image separator
+ readBitmap();
+ break;
+ case 0x21: // extension
+ code = read();
+ switch (code) {
+ case 0xf9: // graphics control extension
+ readGraphicControlExt();
+ break;
+ case 0xff: // application extension
+ readBlock();
+ StringBuilder app = new StringBuilder();
+ for (int i = 0; i < 11; i++) {
+ app.append((char) block[i]);
+ }
+ if ("NETSCAPE2.0".equals(app.toString())) {
+ readNetscapeExt();
+ } else {
+ skip(); // don't care
+ }
+ break;
+ // comment extension
+ // plain text extension
+ default: // uninteresting extension
+ skip();
+ }
+ break;
+ case 0x3b: // terminator
+ done = true;
+ break;
+ case 0x00: // bad byte, but keep going and see what happens
+ break;
+ default:
+ status = STATUS_FORMAT_ERROR;
+ }
+ }
+ }
+
+ /**
+ * Reads a single byte from the input stream.
+ */
+ protected int read() {
+ int curByte = 0;
+ try {
+ curByte = in.read();
+ } catch (Exception e) {
+ status = STATUS_FORMAT_ERROR;
+ }
+ return curByte;
+ }
+
+ /**
+ * Reads GIF file header information.
+ */
+ protected void readHeader() {
+ StringBuilder id = new StringBuilder();
+ for (int i = 0; i < 6; i++) {
+ id.append((char) read());
+ }
+ if (!id.toString().startsWith("GIF")) {
+ status = STATUS_FORMAT_ERROR;
+ return;
+ }
+ readLSD();
+ if (gctFlag && !err()) {
+ gct = readColorTable(gctSize);
+ bgColor = gct[bgIndex];
+ }
+ }
+
+ /**
+ * Reads color table as 256 RGB integer values
+ *
+ * @param ncolors int number of colors to read
+ * @return int array containing 256 colors (packed ARGB with full alpha)
+ */
+ protected int[] readColorTable(int ncolors) {
+ int nbytes = 3 * ncolors;
+ int[] tab = null;
+ byte[] c = new byte[nbytes];
+ int n = 0;
+ try {
+ n = in.read(c);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ if (n < nbytes) {
+ status = STATUS_FORMAT_ERROR;
+ } else {
+ tab = new int[256]; // max size to avoid bounds checks
+ int i = 0;
+ int j = 0;
+ while (i < ncolors) {
+ int r = ((int) c[j++]) & 0xff;
+ int g = ((int) c[j++]) & 0xff;
+ int b = ((int) c[j++]) & 0xff;
+ tab[i++] = 0xff000000 | (r << 16) | (g << 8) | b;
+ }
+ }
+ return tab;
+ }
+
+ public Animation getAnimation(PlayMode playMode) {
+ int nrFrames = getFrameCount();
+ Pixmap frame = getFrame(0);
+ int width = frame.getWidth();
+ int height = frame.getHeight();
+ int vzones = (int) Math.sqrt(nrFrames);
+ int hzones = vzones;
+
+ while (vzones * hzones < nrFrames) vzones++;
+
+ int v;
+ int h;
+
+ Pixmap target = new Pixmap(width * hzones, height * vzones, Pixmap.Format.RGBA8888);
+
+ for (h = 0; h < hzones; h++) {
+ for (v = 0; v < vzones; v++) {
+ int frameID = v + h * vzones;
+ if (frameID < nrFrames) {
+ frame = getFrame(frameID);
+ target.drawPixmap(frame, h * width, v * height);
+ }
+ }
+ }
+
+ Texture texture = new Texture(target);
+ Array texReg = new Array<>();
+
+ for (h = 0; h < hzones; h++) {
+ for (v = 0; v < vzones; v++) {
+ int frameID = v + h * vzones;
+ if (frameID < nrFrames) {
+ TextureRegion tr = new TextureRegion(texture, h * width, v * height, width, height);
+ texReg.add(tr);
+ }
+ }
+ }
+ float frameDuration = (float) getDelay(0);
+ frameDuration /= 1000; // convert milliseconds into seconds
+
+ return new Animation<>(frameDuration, texReg, playMode);
+ }
+
+ /**
+ * Reads Graphics Control Extension values
+ */
+ protected void readGraphicControlExt() {
+ read(); // block size
+ int packed = read(); // packed fields
+ dispose = (packed & 0x1c) >> 2; // disposal method
+ if (dispose == 0) {
+ dispose = 1; // elect to keep old image if discretionary
+ }
+ transparency = (packed & 1) != 0;
+ delay = readShort() * 10; // delay in milliseconds
+ transIndex = read(); // transparent color index
+ read(); // block terminator
+ }
+
+ /**
+ * Reads next frame image
+ */
+ protected void readBitmap() {
+ ix = readShort(); // (sub)image position & size
+ iy = readShort();
+ iw = readShort();
+ ih = readShort();
+ int packed = read();
+ lctFlag = (packed & 0x80) != 0; // 1 - local color table flag interlace
+ lctSize = (int) Math.pow(2, (packed & 0x07) + 1);
+ // 3 - sort flag
+ // 4-5 - reserved lctSize = 2 << (packed & 7); // 6-8 - local color
+ // table size
+ interlace = (packed & 0x40) != 0;
+ if (lctFlag) {
+ lct = readColorTable(lctSize); // read table
+ act = lct; // make local table active
+ } else {
+ act = gct; // make global table active
+ if (bgIndex == transIndex) {
+ bgColor = 0;
+ }
+ }
+ int save = 0;
+ if (transparency) {
+ save = act[transIndex];
+ act[transIndex] = 0; // set transparent color if specified
+ }
+ if (act == null) {
+ status = STATUS_FORMAT_ERROR; // no color table defined
+ }
+ if (err()) {
+ return;
+ }
+ decodeBitmapData(); // decode pixel data
+ skip();
+ if (err()) {
+ return;
+ }
+ frameCount++;
+ // create new image to receive frame data
+ image = new DixieMap(width, height);
+ setPixels(); // transfer pixel data to image
+ frames.addElement(new GifFrame(image, delay)); // add image to frame
+ // list
+ if (transparency) {
+ act[transIndex] = save;
+ }
+ resetFrame();
+ }
+
+ private static class DixieMap extends Pixmap {
+ DixieMap(int w, int h) {
+ super(w, h, Format.RGBA8888);
+ }
+
+ DixieMap(int[] data, int w, int h) {
+ super(w, h, Format.RGBA8888);
+
+ int x;
+ int y;
+
+ for (y = 0; y < h; y++) {
+ for (x = 0; x < w; x++) {
+ int pxl_ARGB8888 = data[x + y * w];
+ int pxl_RGBA8888 =
+ ((pxl_ARGB8888 >> 24) & 0x000000ff) | ((pxl_ARGB8888 << 8) & 0xffffff00);
+ // convert ARGB8888 > RGBA8888
+ drawPixel(x, y, pxl_RGBA8888);
+ }
+ }
+ }
+
+ private void getPixels(int[] pixels, int offset, int stride, int width, int height) {
+ java.nio.ByteBuffer bb = getPixels();
+
+ int k;
+ int l;
+
+ for (k = 0; k < height; k++) {
+ int _offset = offset;
+ for (l = 0; l < width; l++) {
+ int pxl = bb.getInt(4 * (l + k * width));
+
+ // convert RGBA8888 > ARGB8888
+ pixels[_offset++] = ((pxl >> 8) & 0x00ffffff) | ((pxl << 24) & 0xff000000);
+ }
+ offset += stride;
+ }
+ }
+ }
+
+ /**
+ * Reads Logical Screen Descriptor
+ */
+ protected void readLSD() {
+ // logical screen size
+ width = readShort();
+ height = readShort();
+ // packed fields
+ int packed = read();
+ gctFlag = (packed & 0x80) != 0; // 1 : global color table flag
+ // 2-4 : color resolution
+ // 5 : gct sort flag
+ gctSize = 2 << (packed & 7); // 6-8 : gct size
+ bgIndex = read(); // background color index
+ pixelAspect = read(); // pixel aspect ratio
+ }
+
+ /**
+ * Reads Netscape extenstion to obtain iteration count
+ */
+ protected void readNetscapeExt() {
+ do {
+ readBlock();
+ if (block[0] == 1) {
+ // loop count sub-block
+ int b1 = ((int) block[1]) & 0xff;
+ int b2 = ((int) block[2]) & 0xff;
+ loopCount = (b2 << 8) | b1;
+ }
+ } while ((blockSize > 0) && !err());
+ }
+
+ /**
+ * Reads next 16-bit value, LSB first
+ */
+ protected int readShort() {
+ // read 16-bit value, LSB first
+ return read() | (read() << 8);
+ }
+
+ /**
+ * Resets frame state for reading next image.
+ */
+ protected void resetFrame() {
+ lastDispose = dispose;
+ lrx = ix;
+ lry = iy;
+ lrw = iw;
+ lrh = ih;
+ lastPixmap = image;
+ lastBgColor = bgColor;
+ dispose = 0;
+ transparency = false;
+ delay = 0;
+ lct = null;
+ }
+
+ /**
+ * Skips variable length blocks up to and including next zero length block.
+ */
+ protected void skip() {
+ do {
+ readBlock();
+ } while ((blockSize > 0) && !err());
+ }
+
+ private static class GifFrame {
+ public final DixieMap image;
+ public final int delay;
+
+ public GifFrame(DixieMap im, int del) {
+ image = im;
+ delay = del;
+ }
+ }
+
+ public static Animation loadGIFAnimation(Animation.PlayMode playMode, InputStream is) {
+ GifDecoder gdec = new GifDecoder();
+ gdec.read(is);
+ return gdec.getAnimation(playMode);
+ }
+}
diff --git a/src/main/java/inf112/skeleton/app/Main.java b/src/main/java/inf112/skeleton/app/Main.java
index 9e64dcf5..bdafade1 100644
--- a/src/main/java/inf112/skeleton/app/Main.java
+++ b/src/main/java/inf112/skeleton/app/Main.java
@@ -10,6 +10,7 @@ public static void main(String[] args) {
cfg.title = "robo-rally";
cfg.width = 960;
cfg.height = 540;
+ //cfg.fullscreen = true;
new LwjglApplication(new RallyGame(), cfg);
}
diff --git a/src/main/java/inf112/skeleton/app/Player.java b/src/main/java/inf112/skeleton/app/Player.java
index a65ad98a..38b3b90c 100644
--- a/src/main/java/inf112/skeleton/app/Player.java
+++ b/src/main/java/inf112/skeleton/app/Player.java
@@ -2,32 +2,112 @@
import com.badlogic.gdx.math.Vector2;
+import inf112.skeleton.app.cards.Deck;
+import inf112.skeleton.app.cards.ProgramCard;
import inf112.skeleton.app.enums.Direction;
+import inf112.skeleton.app.objects.Flag;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
public class Player {
private final int playerNr;
private Vector2 backupPosition;
- private Vector2 position;
+ private Direction backupDirection;
+ private Vector2 alternativeBackupPosition;
+ private Direction alternativeBackupDirection;
+ private final Vector2 position;
private Direction direction;
+ private final ArrayList flagsCollected;
+ private ArrayList selectedCards;
+ private final ArrayList allCards;
+
+ private int damageTokens;
+ private int lifeTokens;
public Player(Vector2 position, int playerNr) {
this.position = position;
this.direction = Direction.EAST;
this.playerNr = playerNr;
- setBackupPosition(position);
+ this.flagsCollected = new ArrayList<>();
+ this.selectedCards = new ArrayList<>();
+ this.allCards = new ArrayList<>();
+ this.damageTokens = 0;
+ this.lifeTokens = 3;
+
+ setBackup(position, Direction.EAST);
+ }
+
+ public ArrayList getAllCards() {
+ return allCards;
+ }
+
+ public ArrayList getSelectedCards() {
+ System.out.println(selectedCards);
+ return selectedCards;
+ }
+
+ public void selectCards() {
+ while (selectedCards.size() < 5) {
+ selectedCards.add(allCards.remove(0));
+ }
+ }
+
+ public void drawCards(Deck deck) {
+ while (allCards.size() < 9) {
+ allCards.add(deck.drawCard());
+ }
}
/**
- * Set new backup position
- * @param backupPosition respawn position when damaged
+ * a int on how many damageTokens
+ *
+ * @return your damageTokens
*/
- public void setBackupPosition(Vector2 backupPosition) {
+ public int getDamageTokens() {
+ return damageTokens;
+ }
+
+ public int resetDamageTokens() {
+ return this.damageTokens = 0;
+ }
+
+ public int getLifeTokens() {
+ return lifeTokens;
+ }
+
+ public void decrementLifeTokens() {
+ this.lifeTokens--;
+ }
+
+ public boolean isDead() {
+ return lifeTokens <= 0;
+ }
+
+ public void handleDamage(RallyGame game) {
+ this.damageTokens++;
+ if (damageTokens >= 10) {
+ lifeTokens--;
+ resetDamageTokens();
+ game.getBoard().respawn(this);
+ }
+ }
+
+ /**
+ * Set new backup position and direction
+ *
+ * @param backupPosition respawn position when damaged
+ * @param backupDirection respawn direction when damaged
+ */
+ public void setBackup(Vector2 backupPosition, Direction backupDirection) {
if (this.backupPosition == null) {
- this.backupPosition = new Vector2(backupPosition.x, backupPosition.y);
+ this.backupPosition = new Vector2(backupPosition);
} else {
this.backupPosition.set(backupPosition.x, backupPosition.y);
}
+ this.backupDirection = backupDirection;
}
/**
@@ -37,10 +117,60 @@ public Vector2 getBackupPosition() {
return backupPosition;
}
+ /**
+ * @return backup direction
+ */
+ public Direction getBackupDirection() {
+ return backupDirection;
+ }
+
+ public void setAlternativeBackup(Vector2 alternativeBackupPosition, Direction alternativeBackupDirection) {
+ if (this.alternativeBackupPosition == null) {
+ this.alternativeBackupPosition = new Vector2(alternativeBackupPosition);
+ } else {
+ this.alternativeBackupPosition.set(alternativeBackupPosition.x, alternativeBackupPosition.y);
+ }
+ this.alternativeBackupDirection = alternativeBackupDirection;
+ }
+
+ /**
+ * @return alternative backup position
+ */
+ public Vector2 getAlternativeBackupPosition() {
+ return alternativeBackupPosition;
+ }
+
+ /**
+ * @return alternative backup direction
+ */
+ public Direction getAlternativeBackupDirection() {
+ return alternativeBackupDirection;
+ }
+
+
+ public void chooseAlternativeBackupPosition(Board board, Vector2 position) {
+ ArrayList possiblePositions = board.getNeighbourhood(position);
+ Collections.shuffle(possiblePositions);
+ for (Vector2 pos : possiblePositions) {
+ for (Direction dir : board.getDirectionRandomOrder()) {
+ if (board.validRespawnPosition(pos, dir)) {
+ setAlternativeBackup(pos, dir);
+ return;
+ }
+ }
+ }
+ setAlternativeBackup(board.getStartPosition(getPlayerNr()), Direction.EAST);
+ if (board.hasPlayer(board.getStartPosition(getPlayerNr()))) {
+ chooseAlternativeBackupPosition(board, alternativeBackupPosition);
+ }
+ }
+
/**
* @return number of player
*/
- public int getPlayerNr() {return playerNr; }
+ public int getPlayerNr() {
+ return playerNr;
+ }
/**
* @return the {@link Vector2} to the player
@@ -69,4 +199,58 @@ public Direction getDirection() {
public void setDirection(Direction direction) {
this.direction = direction;
}
+
+ public void pickUpFlag(Flag flag, int flagNr) {
+ switch (flagNr) {
+ case 1:
+ if (!flagsCollected.contains(flag)) {
+ flagsCollected.add(flag);
+ }
+ break;
+ case 2:
+ if (!flagsCollected.contains(flag) && flagsCollected.size() == 1) {
+ flagsCollected.add(flag);
+ }
+ break;
+ case 3:
+ if (!flagsCollected.contains(flag) && flagsCollected.size() == 2) {
+ flagsCollected.add(flag);
+ }
+ break;
+ case 4:
+ if (!flagsCollected.contains(flag) && flagsCollected.size() == 3) {
+ flagsCollected.add(flag);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Update the selected cards for this player.
+ * Used for testing, so that we can decide what card the player is going to play, and then test that the player
+ * does what the card says.
+ *
+ * @param cards one or more cards (separated by comma) or a list of cards.
+ */
+ public void setSelectedCards(ProgramCard... cards) {
+ this.selectedCards = new ArrayList<>(Arrays.asList(cards));
+ }
+
+ public ArrayList getFlagsCollected() {
+ return flagsCollected;
+ }
+
+ public boolean hasAllFlags(int numberOfFlags) {
+ return flagsCollected.size() == numberOfFlags;
+ }
+
+ public boolean equals(Player other) {
+ return this.getPlayerNr() == other.getPlayerNr();
+ }
+
+ public String toString() {
+ return "Player " + getPlayerNr();
+ }
}
diff --git a/src/main/java/inf112/skeleton/app/PlayerSorter.java b/src/main/java/inf112/skeleton/app/PlayerSorter.java
new file mode 100644
index 00000000..7c7bea8e
--- /dev/null
+++ b/src/main/java/inf112/skeleton/app/PlayerSorter.java
@@ -0,0 +1,12 @@
+package inf112.skeleton.app;
+
+import java.util.Comparator;
+
+public class PlayerSorter implements Comparator {
+
+ @Override
+ public int compare(Player player1, Player player2) {
+ return player2.getSelectedCards().get(0).getPriority() -
+ player1.getSelectedCards().get(0).getPriority();
+ }
+}
diff --git a/src/main/java/inf112/skeleton/app/RallyGame.java b/src/main/java/inf112/skeleton/app/RallyGame.java
index 31c16733..20cff3ce 100644
--- a/src/main/java/inf112/skeleton/app/RallyGame.java
+++ b/src/main/java/inf112/skeleton/app/RallyGame.java
@@ -4,50 +4,270 @@
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputAdapter;
-import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+import com.badlogic.gdx.audio.Music;
+import com.badlogic.gdx.audio.Sound;
+import com.badlogic.gdx.math.Vector2;
import inf112.skeleton.app.cards.Deck;
+import inf112.skeleton.app.cards.ProgramCard;
import inf112.skeleton.app.enums.Direction;
-import inf112.skeleton.app.screens.MenuScreen;
+import inf112.skeleton.app.enums.Rotate;
+import inf112.skeleton.app.objects.Laser;
+import inf112.skeleton.app.objects.RotatePad;
+import inf112.skeleton.app.screens.GifScreen;
+import inf112.skeleton.app.screens.LoadingScreen;
+
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
public class RallyGame extends Game {
public Board board;
- public SpriteBatch batch;
public Deck deck;
+ public ArrayList players;
+ public Semaphore waitForCards;
+ public boolean playing;
+ public Sound laserSound;
+ public Player mainPlayer;
public void create() {
- this.batch = new SpriteBatch();
- this.board = new Board("assets/Risky_Exchange.tmx");
- this.setScreen(new MenuScreen(this));
+ this.setScreen(new LoadingScreen(this));
+ startMusic();
+ }
+
+ public void setupGame(String mapPath) {
+ this.board = new Board(mapPath, 4);
this.deck = new Deck();
+ this.players = new ArrayList<>();
+ this.players = board.getPlayers();
+ this.mainPlayer = board.getPlayer1();
+
+ this.waitForCards = new Semaphore(1);
+ this.waitForCards.tryAcquire();
+ this.playing = true;
+ this.laserSound = Gdx.audio.newSound(Gdx.files.internal("assets/Sound/LaserShot.mp3"));
+
+ new Thread(this::doTurn).start();
+
+ setInputProcessor();
+ dealCards();
+ selectCards();
+ }
+
+ public void setInputProcessor() {
Gdx.input.setInputProcessor(new InputAdapter() {
@Override
public boolean keyUp(int keycode) {
- Player player = board.getPlayer1();
+ if (mainPlayer.isDead()) {
+ return false;
+ }
+
+ removeLasers();
+
if (keycode == Input.Keys.RIGHT) {
- player.setDirection(Direction.EAST);
+ mainPlayer.setDirection(Direction.EAST);
+ board.movePlayer(mainPlayer);
} else if (keycode == Input.Keys.LEFT) {
- player.setDirection(Direction.WEST);
+ mainPlayer.setDirection(Direction.WEST);
+ board.movePlayer(mainPlayer);
} else if (keycode == Input.Keys.UP) {
- player.setDirection(Direction.NORTH);
+ mainPlayer.setDirection(Direction.NORTH);
+ board.movePlayer(mainPlayer);
} else if (keycode == Input.Keys.DOWN) {
- player.setDirection(Direction.SOUTH);
+ mainPlayer.setDirection(Direction.SOUTH);
+ board.movePlayer(mainPlayer);
+ } else if (keycode == Input.Keys.ESCAPE) {
+ Gdx.app.exit();
+ } else if (keycode == Input.Keys.SPACE) {
+ cardsReady();
+ return super.keyDown(keycode);
} else {
return super.keyDown(keycode);
}
- board.movePlayer(player);
+
+ if (mainPlayer.hasAllFlags(board.getFlags().size())) {
+ setWinScreen();
+ }
+ board.respawnPlayers();
+ fireLasers();
+ removeDeadPlayers();
return super.keyDown(keycode);
}
});
}
- public void render() {
- super.render();
+ public void startMusic() {
+ Music music = Gdx.audio.newMusic(Gdx.files.internal("assets/sound/menu_music.mp3"));
+ music.setLooping(true);
+ music.setVolume(1f);
+ music.play();
+ }
+
+ private void cardsReady() {
+ waitForCards.release();
+ }
+
+ public void doTurn() {
+
+ // TODO: Alle velger kort
+ // TODO: Første kort spilles for alle i riktig rekkefølge
+ // TODO: Gears roterer
+ // TODO: Express belt flytter én
+ // TODO: Express belt og vanlig belt flytter én
+ // TODO: Spiller skyter
+ // TODO: Laser skyter
+ while (playing) {
+ try {
+ waitForCards.acquire();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ if (Thread.interrupted()) {
+ return;
+ }
+ for (int i = 0; i < 5; i++) {
+ System.out.println("Runde " + (i + 1));
+ allPlayersPlayCard();
+ activateRotatePads();
+
+ fireLasers();
+ try {
+ Thread.sleep(600);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ removeLasers();
+ }
+ removeDeadPlayers();
+ dealCards();
+ selectCards();
+ }
+ }
+
+ public void selectCards() {
+ for (Player player : players) {
+ player.selectCards();
+ }
+ }
+
+ public void dealCards() {
+ for (Player player : players) {
+ player.drawCards(deck);
+ }
+ }
+
+ public void removeDeadPlayers() {
+ ArrayList deadPlayers = new ArrayList<>();
+ for (Player player : players) {
+ if (player.isDead()) {
+ board.removePlayerFromBoard(player);
+ deadPlayers.add(player);
+ }
+ }
+ players.removeAll(deadPlayers);
+ }
+
+ public void allPlayersPlayCard() {
+ ArrayList playerOrder = new ArrayList<>(players);
+ // Add all players to order list, and remove players with no cards left
+ playerOrder.removeIf(p -> p.getSelectedCards().isEmpty());
+ playerOrder.sort(new PlayerSorter());
+ for (Player player : playerOrder) {
+ playCard(player);
+ // Wait 1 second for each player
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public void playCard(Player player) {
+ ProgramCard card = player.getSelectedCards().remove(0);
+ System.out.println(player.toString() + " played " + card.toString());
+ switch (card.getRotate()) {
+ case RIGHT:
+ player.setDirection(player.getDirection().turnRight());
+ board.rotatePlayer(player);
+ break;
+ case LEFT:
+ player.setDirection(player.getDirection().turnLeft());
+ board.rotatePlayer(player);
+ break;
+ case UTURN:
+ player.setDirection(player.getDirection().turnAround());
+ board.rotatePlayer(player);
+ break;
+ case NONE:
+ for (int i = 0; i < card.getDistance(); i++) {
+ board.movePlayer(player);
+ // Wait 500 ms for each move except last one
+ if (i < card.getDistance() - 1) {
+ try {
+ Thread.sleep(500);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ deck.addCardToDiscardPile(card);
+ }
+
+ public void setWinScreen() {
+ this.dispose();
+ this.setScreen(new GifScreen(this));
+ }
+
+ public void removeLasers() {
+ for (int y = 0; y < board.getHeight(); y++) {
+ for (int x = 0; x < board.getWidth(); x++) {
+ board.laserLayer.setCell(x, y, null);
+ }
+ }
+ }
+
+ public void fireLasers() {
+ for (Laser laser : board.lasers) {
+ laser.fire(this);
+ }
+ laserSound.play();
+ }
+
+ public void activateRotatePads(){
+ for(Player player : board.getPlayers()){
+ for(RotatePad rotatePad : board.rotatePads){
+ Vector2 playerPosition = player.getPosition();
+ Vector2 rotePadPosition = rotatePad.getPosition();
+
+ if(playerPosition.equals(rotePadPosition)){
+ Rotate rotateDirection = rotatePad.getRotate();
+ Direction playerDirection = player.getDirection();
+
+ switch (rotateDirection){
+ case LEFT:
+ player.setDirection(playerDirection.turnLeft());
+ break;
+ case RIGHT:
+ player.setDirection(playerDirection.turnRight());
+ break;
+ case UTURN:
+ player.setDirection(playerDirection.turnAround());
+ break;
+ default:
+ // Will never happen
+ }
+ }
+ }
+ }
}
public void dispose() {
- batch.dispose();
+ this.screen.dispose();
}
public Board getBoard() {
diff --git a/src/main/java/inf112/skeleton/app/cards/CardHand.java b/src/main/java/inf112/skeleton/app/cards/CardHand.java
deleted file mode 100644
index 9234cf98..00000000
--- a/src/main/java/inf112/skeleton/app/cards/CardHand.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package inf112.skeleton.app.cards;
-
-import java.util.ArrayList;
-
-public class CardHand {
-
- private ArrayList hand = new ArrayList<>();
-
- public CardHand(Deck deck, int slots) {
- for (int i = 0; i < slots; i++) {
- hand.add(deck.drawCard());
- }
- }
-
-}
diff --git a/src/main/java/inf112/skeleton/app/cards/Deck.java b/src/main/java/inf112/skeleton/app/cards/Deck.java
index f665fa78..cc445670 100644
--- a/src/main/java/inf112/skeleton/app/cards/Deck.java
+++ b/src/main/java/inf112/skeleton/app/cards/Deck.java
@@ -7,9 +7,7 @@
public class Deck {
private Stack deck;
-
- private ProgramCard card;
- private int priority = 0;
+ private Stack discardPile;
public Deck() {
makeNewDeck();
@@ -17,13 +15,17 @@ public Deck() {
}
/**
- * Makes all the programCards and puts them on the stack
+ * Make all the programCards and put them in the stack
*/
public void makeNewDeck() {
deck = new Stack<>();
+ discardPile = new Stack<>();
+ makeRotateCards();
+ makeMoveCards();
+ }
- priority = makeRotateCards(priority);
- makeMoveCards(priority);
+ public void addCardToDiscardPile(ProgramCard programCard) {
+ discardPile.push(programCard);
}
/**
@@ -44,62 +46,48 @@ public void shuffleDeck() {
* @return the next {@link ProgramCard} in the stack / deck
*/
public ProgramCard drawCard() {
- return deck.pop();
+ ProgramCard card = deck.pop();
+ if (deck.isEmpty()) {
+ deck.addAll(discardPile);
+ shuffleDeck();
+ }
+ return card;
}
/**
- * Makes all the rotating cards, RotateR (18), RotateL (18) and RotateU (6) cards.
- * @param startPri is the priority number the last card made had.
- * @return the priority number of the last card made
+ * Make all rotate cards, 18 Rotate right, 18 Rotate left and 6 Rotate U-turn
+ * with priority evenly spread between all cards
*/
- private int makeRotateCards(int startPri){
- int priority = startPri;
- for (int i = 0; i < 36; i++) {
- priority += 10;
- if (i % 2 == 0) {
- card = new ProgramCard(priority, 0, Rotate.LEFT, "Rotate Left");
+ private void makeRotateCards() {
+ // Make 42 rotate cards
+ for (int priority = 1; priority <= 42; priority++) {
+ // Every seventh rotate card should be U-turn
+ if (priority % 7 == 0) {
+ deck.push(new ProgramCard(priority * 10, 0, Rotate.UTURN, "U-turn"));
+ } else if (priority % 2 == 0) {
+ deck.push(new ProgramCard(priority * 10, 0, Rotate.RIGHT, "Right rotate"));
} else {
- card = new ProgramCard(priority, 0, Rotate.RIGHT, "Rotate Right");
+ deck.push(new ProgramCard(priority * 10, 0, Rotate.LEFT, "Left rotate"));
}
- deck.push(card);
}
- for (int i = 0; i < 6; i++) {
- priority += 10;
- card = new ProgramCard(priority, 0, Rotate.UTURN, "U-Turn");
- deck.push(card);
- }
- return priority;
}
/**
- * Makes all the move cards, Move 1 (18), Move 2 (12) and Move 3 (6).
- * @param startPri is the priority number of the last card made had.
+ * Make all move cards, 18 Move 1, 12 Move 2 and 6 Move 3
+ * with priority evenly spread between all cards
*/
- private void makeMoveCards(int startPri){
- int priority = startPri;
- boolean checker = true;
- for (int i = 0; i < 30; i++) {
- priority += 10;
-
- // This is so the move tre cards not all get in the same range of priority.
- if (i % 3 == 0 && i < 18) {
- card = new ProgramCard(priority, 3, Rotate.NONE, "Move 3");
+ private void makeMoveCards() {
+ int startPriority = 420;
+ // Make 36 move cards
+ for (int priority = 1; priority <= 36; priority++) {
+ if (priority % 6 == 0) {
+ // For every sixth card there should be one move 3, two move 2 and three move 1 cards
+ deck.push(new ProgramCard(priority * 10 + startPriority, 3, Rotate.NONE, "Move 3"));
+ } else if ((priority + 1) % 6 == 0 || (priority + 2) % 6 == 0) {
+ deck.push(new ProgramCard(priority * 10 + startPriority, 2, Rotate.NONE, "Move 2"));
} else {
- if (checker) {
- card = new ProgramCard(priority, 2, Rotate.NONE, "Move 2");
- checker = false;
- } else {
- card = new ProgramCard(priority, 1, Rotate.NONE, "Move 1");
- checker = true;
- }
+ deck.push(new ProgramCard(priority * 10 + startPriority, 1, Rotate.NONE, "Move 1"));
}
- deck.push(card);
- }
- // Making the last 6 Move 1 cards
- for (int i = 0; i < 6; i++) {
- priority += 10;
- card = new ProgramCard(priority, 1, Rotate.NONE, "Move 1");
- deck.push(card);
}
}
}
diff --git a/src/main/java/inf112/skeleton/app/cards/ProgramCard.java b/src/main/java/inf112/skeleton/app/cards/ProgramCard.java
index 3e891c1f..0d9a226e 100644
--- a/src/main/java/inf112/skeleton/app/cards/ProgramCard.java
+++ b/src/main/java/inf112/skeleton/app/cards/ProgramCard.java
@@ -3,11 +3,11 @@
import inf112.skeleton.app.enums.Rotate;
public class ProgramCard {
- private int priority;
- private int distance;
- private String name;
+ private final int priority;
+ private final int distance;
+ private final String name;
- private Rotate rotate;
+ private final Rotate rotate;
public ProgramCard(int priority, int distance, Rotate rotate, String name) {
this.priority = priority;
@@ -28,7 +28,7 @@ public Rotate getRotate() {
return rotate;
}
- public String getName() {
- return name;
+ public String toString() {
+ return name + ": " + priority;
}
}
diff --git a/src/main/java/inf112/skeleton/app/enums/Direction.java b/src/main/java/inf112/skeleton/app/enums/Direction.java
index 44971933..efff143a 100644
--- a/src/main/java/inf112/skeleton/app/enums/Direction.java
+++ b/src/main/java/inf112/skeleton/app/enums/Direction.java
@@ -24,16 +24,25 @@ public Direction turnRight() {
return getDirection(SOUTH, EAST, NORTH, WEST);
}
+ /**
+ * Turns the {@link Direction} to opposite direction.
+ *
+ * @return {@link Direction} after opposite transformation.
+ */
+ public Direction turnAround() {
+ return getDirection(WEST, SOUTH, EAST, NORTH);
+ }
+
/**
* Help function instead of duplicate code
*
* @param baseCaseEAST The direction it's supposed to be if the case is EAST.
* @param baseCaseNORTH The direction it's supposed to be if the case is NORTH.
* @param baseCaseWEST The direction it's supposed to be if the case is WEST.
- * @param baseCaseSOUT The direction it's supposed to be if the case is SOUTH.
+ * @param baseCaseSOUTH The direction it's supposed to be if the case is SOUTH.
* @return The right facing after a given transformation.
*/
- private Direction getDirection(Direction baseCaseEAST, Direction baseCaseNORTH, Direction baseCaseWEST, Direction baseCaseSOUT) {
+ private Direction getDirection(Direction baseCaseEAST, Direction baseCaseNORTH, Direction baseCaseWEST, Direction baseCaseSOUTH) {
switch (this) {
case EAST:
return baseCaseEAST;
@@ -42,7 +51,7 @@ private Direction getDirection(Direction baseCaseEAST, Direction baseCaseNORTH,
case WEST:
return baseCaseWEST;
case SOUTH:
- return baseCaseSOUT;
+ return baseCaseSOUTH;
default:
return null;
}
diff --git a/src/main/java/inf112/skeleton/app/enums/TileID.java b/src/main/java/inf112/skeleton/app/enums/TileID.java
index e47dd7ab..a49faa9c 100644
--- a/src/main/java/inf112/skeleton/app/enums/TileID.java
+++ b/src/main/java/inf112/skeleton/app/enums/TileID.java
@@ -1,44 +1,73 @@
package inf112.skeleton.app.enums;
public enum TileID {
- STARTPOS1(121),
- STARTPOS2(122),
- STARTPOS3(123),
- STARTPOS4(124),
- STARTPOS5(129),
- STARTPOS6(130),
- STARTPOS7(131),
- STARTPOS8(133),
-
- RIGHT_WALL(23),
- DOWN_WALL(29),
- LEFT_WALL(30),
- UP_WALL(31),
-
- RIGHT_LASER_WALL(46),
- DOWN_LASER_WALL(37),
- LEFT_LASER_WALL(38),
- UP_LASER_WALL(45),
-
- SOUTHEASTWALL(8),
- NORTHEASTWALL(16),
- NORTHWESTWALL(24),
- SOUTHWESTWALL(32),
+ START_POS1(121),
+ START_POS2(122),
+ START_POS3(123),
+ START_POS4(124),
+ START_POS5(129),
+ START_POS6(130),
+ START_POS7(131),
+ START_POS8(133),
+
+ EAST_WALL(23),
+ SOUTH_WALL(29),
+ WEST_WALL(30),
+ NORTH_WALL(31),
+
+ EAST_LASER_WALL(46),
+ SOUTH_LASER_WALL(37),
+ WEST_LASER_WALL(38),
+ NORTH_LASER_WALL(45),
+
+ SOUTHEAST_WALL(8),
+ NORTHEAST_WALL(16),
+ NORTHWEST_WALL(24),
+ SOUTHWEST_WALL(32),
VERTICAL_LASER(47),
HORIZONTAL_LASER(39),
+ CROSSED_LASER(40),
+
+ NORMAL_HOLE(6),
+ NORMAL_HOLE2(91),
+ NORTHWEST_HOLE(105),
+ NORTH_HOLE(106),
+ NORTHEAST_HOLE(107),
+ EAST_HOLE(108),
+ NORTH_EAST_SOUTH_HOLE(109),
+ WEST_EAST_SOUTH_HOLE(110),
+ SOUTHWEST_HOLE(113),
+ SOUTH_HOLE(114),
+ SOUTHEAST_HOLE(115),
+ WEST_HOLE(116),
+ NORTH_WEST_SOUTH_HOLE(117),
+ NORTH_WEST_EAST_HOLE(118),
+
+ ROTATE_PAD_LEFT(53),
+ ROTATE_PAD_RIGHT(54),
WRENCH(14),
- DOUBLE_WRENCH(7);
+ DOUBLE_WRENCH(7),
+
+ PLAYER_SOUTH(137),
+ PLAYER_NORTH(138),
+ PLAYER_EAST(139),
+ PLAYER_WEST(140),
- private int id;
+ FLAG_1(55),
+ FLAG_2(63),
+ FLAG_3(71),
+ FLAG_4(79);
+ private final int id;
+
+ TileID(int id) {
+ this.id = id;
+ }
public int getId() {
return this.id;
}
- private TileID(int id) {
- this.id = id;
- }
}
diff --git a/src/main/java/inf112/skeleton/app/objects/Flag.java b/src/main/java/inf112/skeleton/app/objects/Flag.java
index d9c95143..708c176c 100644
--- a/src/main/java/inf112/skeleton/app/objects/Flag.java
+++ b/src/main/java/inf112/skeleton/app/objects/Flag.java
@@ -5,18 +5,18 @@
public class Flag {
private final int flagnr;
- private Vector2 position;
-
- public Flag(int flagnr, Vector2 position) {
- this.flagnr = flagnr;
- this.position = position;
- }
-
+ private final Vector2 position;
public Flag(int flagnr, int x, int y) {
this.flagnr = flagnr;
this.position = new Vector2(x, y);
}
+ public Vector2 getPosition() {
+ return position;
+ }
+ public int getFlagnr() {
+ return flagnr;
+ }
}
diff --git a/src/main/java/inf112/skeleton/app/objects/Laser.java b/src/main/java/inf112/skeleton/app/objects/Laser.java
new file mode 100644
index 00000000..b8b697c1
--- /dev/null
+++ b/src/main/java/inf112/skeleton/app/objects/Laser.java
@@ -0,0 +1,37 @@
+package inf112.skeleton.app.objects;
+
+import com.badlogic.gdx.math.Vector2;
+import inf112.skeleton.app.RallyGame;
+import inf112.skeleton.app.enums.Direction;
+
+public class Laser {
+
+ final Vector2 startPosition;
+ final Direction direction;
+
+ public Laser(int x, int y, Direction direction) {
+ this.startPosition = new Vector2(x, y);
+ this.direction = direction;
+ }
+
+ public void fire(RallyGame game) {
+ fire(game, startPosition);
+ }
+
+ public void fire(RallyGame game, Vector2 position) {
+ game.getBoard().addLaser(position, direction);
+ if (game.getBoard().hasPlayer(position)) {
+ game.getBoard().getPlayer(position).handleDamage(game);
+ } else if (game.getBoard().canGo(position, this.direction)) {
+ fire(game, game.getBoard().getNeighbourPosition(position, direction));
+ }
+ }
+
+ public Direction getDirection() {
+ return this.direction;
+ }
+
+ public Vector2 getStartPosition() {
+ return this.startPosition;
+ }
+}
diff --git a/src/main/java/inf112/skeleton/app/objects/RotatePad.java b/src/main/java/inf112/skeleton/app/objects/RotatePad.java
new file mode 100644
index 00000000..fa57ab57
--- /dev/null
+++ b/src/main/java/inf112/skeleton/app/objects/RotatePad.java
@@ -0,0 +1,23 @@
+package inf112.skeleton.app.objects;
+
+import com.badlogic.gdx.math.Vector2;
+import inf112.skeleton.app.enums.Rotate;
+
+public class RotatePad {
+ private final Rotate rotate;
+ private final Vector2 position;
+
+ public RotatePad(Rotate rotate, Vector2 vector) {
+ this.rotate = rotate;
+ this.position = vector;
+ }
+
+ public Rotate getRotate() {
+ return rotate;
+ }
+
+
+ public Vector2 getPosition() {
+ return position;
+ }
+}
diff --git a/src/main/java/inf112/skeleton/app/screens/GameScreen.java b/src/main/java/inf112/skeleton/app/screens/GameScreen.java
index 4bdc9cf1..0328a27d 100644
--- a/src/main/java/inf112/skeleton/app/screens/GameScreen.java
+++ b/src/main/java/inf112/skeleton/app/screens/GameScreen.java
@@ -1,69 +1,62 @@
package inf112.skeleton.app.screens;
import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.Screen;
import com.badlogic.gdx.graphics.GL20;
-import com.badlogic.gdx.graphics.OrthographicCamera;
+import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.maps.tiled.TiledMapRenderer;
import com.badlogic.gdx.maps.tiled.renderers.OrthogonalTiledMapRenderer;
-import inf112.skeleton.app.Board;
import inf112.skeleton.app.RallyGame;
-public class GameScreen implements Screen {
+public class GameScreen extends StandardScreen {
- private final RallyGame game;
- private final Board board;
-
- private OrthographicCamera camera;
- private TiledMapRenderer mapRenderer;
+ private final TiledMapRenderer mapRenderer;
+ private final Texture lifeTokens;
+ private final Texture damageTokens;
+ private float tokensX;
+ private float lifeTokensY;
+ private float damageTokensY;
+ private float tokensSize;
public GameScreen(final RallyGame game) {
- camera = new OrthographicCamera();
-
- this.game = game;
- this.board = game.getBoard();
-
- camera.setToOrtho(false, board.getWidth() * 300, board.getHeight() * 300);
+ super(game);
+ lifeTokens = new Texture("assets/images/lifeToken.png");
+ damageTokens = new Texture("assets/images/damageToken.png");
+ super.camera.setToOrtho(false, game.board.getWidth() * 400, game.board.getHeight() * 400);
this.mapRenderer = new OrthogonalTiledMapRenderer(game.getBoard().getMap());
mapRenderer.setView(camera);
- }
-
- @Override
- public void show() {
-
+ updateTokens();
}
@Override
public void render(float v) {
- Gdx.gl.glClearColor(v, v, v, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
+ renderSettings(v);
- camera.update();
- game.batch.setProjectionMatrix(camera.combined);
-
- game.batch.begin();
+ updateTokens();
mapRenderer.render();
- game.batch.end();
+ batch.begin();
+ renderLifeTokens();
+ renderDamageTokens();
+ batch.end();
}
- @Override
- public void resize(int i, int i1) {
+ public void updateTokens() {
+ tokensSize = camera.viewportHeight / 8;
+ tokensX = 10;
+ lifeTokensY = camera.viewportHeight - tokensSize;
+ damageTokensY = lifeTokensY - tokensSize;
}
- @Override
- public void pause() {
- }
-
- @Override
- public void resume() {
+ public void renderDamageTokens() {
+ for (int i = 0; i < game.mainPlayer.getDamageTokens(); i++) {
+ batch.draw(damageTokens, tokensX + i * tokensSize, damageTokensY, tokensSize, tokensSize);
+ }
}
- @Override
- public void hide() {
- }
-
- @Override
- public void dispose() {
+ public void renderLifeTokens() {
+ for (int i = 0; i < game.mainPlayer.getLifeTokens(); i++) {
+ batch.draw(lifeTokens, tokensX + i * tokensSize, lifeTokensY, tokensSize, tokensSize);
+ }
}
}
diff --git a/src/main/java/inf112/skeleton/app/screens/GifScreen.java b/src/main/java/inf112/skeleton/app/screens/GifScreen.java
new file mode 100644
index 00000000..0d353590
--- /dev/null
+++ b/src/main/java/inf112/skeleton/app/screens/GifScreen.java
@@ -0,0 +1,32 @@
+package inf112.skeleton.app.screens;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.g2d.Animation;
+import com.badlogic.gdx.graphics.g2d.TextureRegion;
+import inf112.skeleton.app.GifDecoder;
+import inf112.skeleton.app.RallyGame;
+
+public class GifScreen extends StandardScreen {
+
+ private final Animation animation;
+ private float elapsed;
+
+ public GifScreen(final RallyGame game) {
+ super(game);
+ this.animation = GifDecoder.loadGIFAnimation(Animation.PlayMode.LOOP, Gdx.files.internal("assets/images/optimusBoi.gif").read());
+ }
+
+ @Override
+ public void render(float v) {
+ renderSettings(v);
+
+ elapsed += Gdx.graphics.getDeltaTime();
+ batch.begin();
+ batch.draw(animation.getKeyFrame(elapsed), 0, 0, camera.viewportWidth, camera.viewportHeight);
+ batch.end();
+ if (animation.isAnimationFinished(elapsed)) {
+ this.dispose();
+ game.setScreen(new YouWinScreen(game));
+ }
+ }
+}
diff --git a/src/main/java/inf112/skeleton/app/screens/LoadingScreen.java b/src/main/java/inf112/skeleton/app/screens/LoadingScreen.java
new file mode 100644
index 00000000..0db8d3d1
--- /dev/null
+++ b/src/main/java/inf112/skeleton/app/screens/LoadingScreen.java
@@ -0,0 +1,34 @@
+package inf112.skeleton.app.screens;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.graphics.Texture;
+import inf112.skeleton.app.RallyGame;
+
+public class LoadingScreen extends StandardScreen {
+
+ private final Texture background;
+ public LoadingScreen(final RallyGame game) {
+ super(game);
+ background = new Texture("assets/images/RoboRallyMenuScreen.png");
+ }
+
+ @Override
+ public void render(float v) {
+ renderSettings(v);
+
+ batch.begin();
+ batch.draw(background, 0, 0, camera.viewportWidth, camera.viewportHeight);
+ batch.end();
+
+ if (Gdx.input.isTouched()) {
+ game.dispose();
+ game.setScreen(new MenuScreen(game));
+ }
+ }
+
+ @Override
+ public void dispose() {
+ background.dispose();
+ super.dispose();
+ }
+}
diff --git a/src/main/java/inf112/skeleton/app/screens/MenuScreen.java b/src/main/java/inf112/skeleton/app/screens/MenuScreen.java
index 5633e2d1..7b761eb3 100644
--- a/src/main/java/inf112/skeleton/app/screens/MenuScreen.java
+++ b/src/main/java/inf112/skeleton/app/screens/MenuScreen.java
@@ -1,66 +1,140 @@
package inf112.skeleton.app.screens;
import com.badlogic.gdx.Gdx;
-import com.badlogic.gdx.Screen;
-import com.badlogic.gdx.graphics.GL20;
-import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
+import com.badlogic.gdx.scenes.scene2d.Stage;
+import com.badlogic.gdx.scenes.scene2d.ui.SelectBox;
+import com.badlogic.gdx.scenes.scene2d.ui.Skin;
+import com.badlogic.gdx.utils.Array;
import inf112.skeleton.app.RallyGame;
-public class MenuScreen implements Screen {
+import java.io.File;
+import java.util.Objects;
- private final RallyGame game;
- private OrthographicCamera camera;
- private Texture background;
+public class MenuScreen extends StandardScreen {
- public MenuScreen(final RallyGame game) {
- this.game = game;
- this.background = new Texture("assets/RoboRallyMenuScreen.png");
- camera = new OrthographicCamera();
- camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
+ private float BUTTON_WIDTH;
+ private float BUTTON_HEIGHT;
+ private float BUTTON_X;
+ private float START_BUTTON_Y;
+ private float EXIT_BUTTON_Y;
+
+ public final SelectBox selectMap;
+
+ private final Texture background;
+ private final Texture startButtonInactive;
+ private final Texture startButtonActive;
+ private final Texture exitButtonInactive;
+ private final Texture exitButtonActive;
+
+ private final Stage stage;
+ public String select;
+
+ public MenuScreen(RallyGame game) {
+ super(game);
+ stage = new Stage();
+ Skin skin = new Skin(Gdx.files.internal("assets/skins/uiskin.json"));
+
+ updateButtons();
+
+ background = new Texture("assets/images/GUI_Edited.jpg");
+ startButtonActive = new Texture("assets/images/Start_Button.png");
+ startButtonInactive = new Texture("assets/images/Start_Button_Active.png");
+ exitButtonInactive = new Texture("assets/images/Exit_Button_Active.png");
+ exitButtonActive = new Texture("assets/images/Exit_Button_Inactive.png");
+
+ selectMap = new SelectBox<>(skin);
+ selectMap.setItems(getMaps());
+ selectMap.setSelected("assets/maps/Risky_Exchange.tmx");
+ selectMap.setWidth(BUTTON_WIDTH * .87f);
+ selectMap.setPosition(BUTTON_X - selectMap.getWidth(), START_BUTTON_Y - BUTTON_HEIGHT / 2);
+
+ stage.addActor(selectMap);
+ }
+
+ private Array getMaps() {
+ Array mapArray = new Array<>();
+ File maps = new File("assets/maps");
+ for (String fileType : Objects.requireNonNull(maps.list())) {
+ if (fileType.endsWith(".tmx")) {
+ mapArray.add(fileType.substring(0, fileType.length() - 4));
+ }
+ }
+ return mapArray;
+ }
+
+ public void updateButtons() {
+ BUTTON_WIDTH = (float) (Gdx.graphics.getWidth() / 4.0);
+ BUTTON_HEIGHT = (float) (Gdx.graphics.getHeight() / 4.0);
+ START_BUTTON_Y = (float) (Gdx.graphics.getHeight() / 2.0);
+ EXIT_BUTTON_Y = (float) (Gdx.graphics.getHeight() / 2.0 - BUTTON_HEIGHT);
+ BUTTON_X = (float) (Gdx.graphics.getWidth() / 2.0 - BUTTON_WIDTH / 2);
}
@Override
public void show() {
+ Gdx.input.setInputProcessor(stage);
+ render(0);
}
@Override
public void render(float v) {
- Gdx.gl.glClearColor(255, 0, 0, 1);
- Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
+ renderSettings(v);
+ updateButtons();
- camera.update();
- game.batch.setProjectionMatrix(camera.combined);
+ batch.begin();
+ batch.draw(background, 0, 0, camera.viewportWidth, camera.viewportHeight);
- game.batch.begin();
- game.batch.draw(background, 0, 0, camera.viewportWidth, camera.viewportHeight);
- game.batch.end();
+ if (mouseOnExit()) {
+ batch.draw(exitButtonActive, BUTTON_X, EXIT_BUTTON_Y, BUTTON_WIDTH, BUTTON_HEIGHT);
+ if (Gdx.input.isTouched()) {
+ Gdx.app.exit();
+ }
+ } else {
+ batch.draw(exitButtonInactive, BUTTON_X, EXIT_BUTTON_Y, BUTTON_WIDTH, BUTTON_HEIGHT);
+ }
- if (Gdx.input.isTouched()) {
- game.setScreen(new GameScreen(game));
- dispose();
+ if (mouseOnStart()) {
+ batch.draw(startButtonActive, BUTTON_X, START_BUTTON_Y, BUTTON_WIDTH, BUTTON_HEIGHT);
+ if (Gdx.input.isTouched()) {
+ game.setupGame("assets/maps/" + getBoard() + ".tmx");
+ this.dispose();
+ game.setScreen(new GameScreen(game));
+ }
+ } else {
+ batch.draw(startButtonInactive, BUTTON_X, START_BUTTON_Y, BUTTON_WIDTH, BUTTON_HEIGHT);
}
+
+ batch.end();
+ stage.act(v);
+ stage.draw();
}
- @Override
- public void resize(int i, int i1) {
+ public String getBoard() {
+ select = selectMap.getSelected();
+ return select;
}
- @Override
- public void pause() {
+ private boolean mouseOnButton(float buttonY) {
+ return Gdx.input.getX() < BUTTON_X + BUTTON_WIDTH &&
+ Gdx.input.getX() > BUTTON_X &&
+ camera.viewportHeight - Gdx.input.getY() < buttonY + BUTTON_HEIGHT &&
+ camera.viewportHeight - Gdx.input.getY() > buttonY;
}
- @Override
- public void resume() {
+ private boolean mouseOnExit() {
+ return mouseOnButton(EXIT_BUTTON_Y);
}
- @Override
- public void hide() {
+ private boolean mouseOnStart() {
+ return mouseOnButton(START_BUTTON_Y);
}
@Override
public void dispose() {
+ stage.dispose();
background.dispose();
+ super.dispose();
}
}
diff --git a/src/main/java/inf112/skeleton/app/screens/StandardScreen.java b/src/main/java/inf112/skeleton/app/screens/StandardScreen.java
new file mode 100644
index 00000000..a94322cb
--- /dev/null
+++ b/src/main/java/inf112/skeleton/app/screens/StandardScreen.java
@@ -0,0 +1,65 @@
+package inf112.skeleton.app.screens;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Screen;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.graphics.OrthographicCamera;
+import com.badlogic.gdx.graphics.g2d.SpriteBatch;
+import inf112.skeleton.app.RallyGame;
+
+public abstract class StandardScreen implements Screen {
+ protected final RallyGame game;
+ protected final OrthographicCamera camera;
+ protected final SpriteBatch batch;
+
+ public StandardScreen(final RallyGame game) {
+ this.game = game;
+ this.batch = new SpriteBatch();
+ this.camera = new OrthographicCamera();
+ this.camera.setToOrtho(false);
+ }
+
+ @Override
+ public void show() {
+ // Empty functions gives bad code quality
+ }
+
+ @Override
+ public void render(float v) {
+ // Empty functions gives bad code quality
+ }
+
+ public void renderSettings(float v) {
+ Gdx.gl.glClearColor(v, v, v, 1);
+ Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
+
+ camera.setToOrtho(false);
+ camera.update();
+ batch.setProjectionMatrix(camera.combined);
+ }
+
+ @Override
+ public void resize(int i, int i1) {
+ // Empty functions gives bad code quality
+ }
+
+ @Override
+ public void pause() {
+ // Empty functions gives bad code quality
+ }
+
+ @Override
+ public void resume() {
+ // Empty functions gives bad code quality
+ }
+
+ @Override
+ public void hide() {
+ // Empty functions gives bad code quality
+ }
+
+ @Override
+ public void dispose() {
+ batch.dispose();
+ }
+}
diff --git a/src/main/java/inf112/skeleton/app/screens/YouWinScreen.java b/src/main/java/inf112/skeleton/app/screens/YouWinScreen.java
new file mode 100644
index 00000000..2c929d13
--- /dev/null
+++ b/src/main/java/inf112/skeleton/app/screens/YouWinScreen.java
@@ -0,0 +1,36 @@
+package inf112.skeleton.app.screens;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.Input;
+import com.badlogic.gdx.graphics.Texture;
+import inf112.skeleton.app.RallyGame;
+
+public class YouWinScreen extends StandardScreen {
+
+ private final Texture background;
+
+ public YouWinScreen(final RallyGame game) {
+ super(game);
+
+ background = new Texture("assets/images/YouWin.png");
+ }
+
+ @Override
+ public void render(float v) {
+ renderSettings(v);
+
+ batch.begin();
+ batch.draw(background, 0, 0, camera.viewportWidth, camera.viewportHeight);
+ batch.end();
+
+ if (Gdx.input.isKeyPressed(Input.Keys.ESCAPE)) {
+ Gdx.app.exit();
+ }
+ }
+
+ @Override
+ public void dispose() {
+ background.dispose();
+ super.dispose();
+ }
+}
diff --git a/src/test/java/inf112/skeleton/app/BoardTest.java b/src/test/java/inf112/skeleton/app/BoardTest.java
index 92dc42fc..4362d675 100644
--- a/src/test/java/inf112/skeleton/app/BoardTest.java
+++ b/src/test/java/inf112/skeleton/app/BoardTest.java
@@ -4,9 +4,14 @@
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.math.Vector2;
import inf112.skeleton.app.enums.Direction;
+import inf112.skeleton.app.objects.Flag;
import org.junit.Before;
import org.junit.Test;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Random;
+
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
@@ -14,10 +19,14 @@
public class BoardTest {
private Board board;
- private final int NUMBER_OF_PLAYERS_WHEN_STARTING_GAME = 2;
+ private final int NUMBER_OF_PLAYERS_WHEN_STARTING_GAME = 0;
private final int BOARD_WIDTH = 16;
private final int BOARD_HEIGHT = 12;
private Player player;
+ private Random random;
+ private ArrayList holes;
+ private Vector2 startPosition;
+ private ArrayList flags;
@Before
public void setUp() {
@@ -26,43 +35,340 @@ public void setUp() {
Gdx.gl = mock(GL20.class);
//Make a headless application in order to initialize the board. Does not show.
new HeadlessApplication(new EmptyApplication());
- this.board = new Board("assets/Risky_Exchange.tmx");
- this.player = new Player(new Vector2(0,0), 1);
+ this.board = new Board("assets/maps/Risky_Exchange.tmx", NUMBER_OF_PLAYERS_WHEN_STARTING_GAME);
+ // Random position
+ this.startPosition = new Vector2(5,5);
+ this.player = new Player(startPosition, 1);
+ this.holes = board.holes;
+ this.flags = board.flags;
+ // Sort the flags so player can go on them in correct order
+ flags.sort(Comparator.comparingInt(Flag::getFlagnr));
+ this.random = new Random();
+ }
+
+ /**
+ * @param flag1 first flag
+ * @param flag2 second flag
+ * @return true if two flags are equal
+ */
+ private boolean isEqualFlags(Flag flag1, Flag flag2) {
+ if (flag1 == null || flag2 == null) {
+ return false;
+ }
+ return flag1.getFlagnr() == flag2.getFlagnr() && flag1.getPosition().equals(flag2.getPosition());
+ }
+
+ /**
+ * @return a random hole position
+ */
+ private Vector2 getRandomHolePosition() {
+ int randomIndex = random.nextInt(holes.size());
+ return holes.get(randomIndex);
+ }
+
+ /**
+ * @return Flag a random flag
+ */
+ private Flag getRandomFlag() {
+ int randomIndex = random.nextInt(flags.size());
+ return flags.get(randomIndex);
+ }
+
+ /**
+ *
+ * @return true if player is on backupPosition and has backupDirection
+ */
+ private boolean isInBackupState(Player player) {
+ return player.getPosition().equals(player.getBackupPosition()) && player.getDirection().equals(player.getBackupDirection());
}
+ @Test
+ public void canNotAddSamePlayerOnBoardTest() {
+ board.addPlayer(player);
+ board.addPlayer(player);
+ assertEquals(1, board.getPlayers().size());
+ }
@Test
- public void whenBoardIsInitializedMapIsNotNullTest() {
+ public void boardHasAMapTest() {
assertNotNull(board.getMap());
}
@Test
- public void whenBoardIsInitializedItHasCorrectNumberOfPlayersTest() {
+ public void correctNumbersOfPlayersOnBoardTest() {
assertEquals(NUMBER_OF_PLAYERS_WHEN_STARTING_GAME, board.getPlayers().size());
}
@Test
- public void whenAPlayerIsAddedTheBoardHasIncrementedPlayersByOneTest() {
- board.addPlayer(0,0, 1);
+ public void aPlayerIsAddedToTheBoardIncrementPlayersTest() {
+ board.addPlayer(player);
assertEquals(NUMBER_OF_PLAYERS_WHEN_STARTING_GAME + 1, board.getPlayers().size());
}
@Test
- public void whenBoardIsInitBoardWidthIsTheSameAsExpectedTest() {
+ public void boardInitializedWithCorrectWidthTest() {
assertEquals(BOARD_WIDTH, board.getWidth());
}
@Test
- public void whenBoardIsInitBoardHeightIsTheSameAsExpectedTest() {
+ public void boardInitializedWithCorrectHeightTest() {
assertEquals(BOARD_HEIGHT, board.getHeight());
}
+
+ @Test
+ public void playerIsOutsideOfUpperBorderTest() {
+ player.setPosition(new Vector2(0, BOARD_HEIGHT));
+ assertTrue(board.outsideBoard(player));
+ }
+
+ @Test
+ public void playerIsOutsideOfRightBorderTest() {
+ player.setPosition(new Vector2(BOARD_WIDTH, 0));
+ assertTrue(board.outsideBoard(player));
+ }
+
+ @Test
+ public void playerIsOutsideOfLeftBorderTest() {
+ player.setPosition(new Vector2(-1, 0));
+ assertTrue(board.outsideBoard(player));
+ }
+
+ @Test
+ public void playerIsUnderBorderTest() {
+ player.setPosition(new Vector2(0, -1));
+ assertTrue(board.outsideBoard(player));
+ }
+
@Test
- public void whenPlayerIsMovedPlayerHasChangedCoordinatesTest() {
+ public void playerOutsideBoardIsRespawnedTest() {
+ Vector2 outsideOfBoardPosition = new Vector2(-1, 0);
+ player.setPosition(outsideOfBoardPosition);
+ board.addPlayer(player);
+ board.respawnPlayers();
+ assertTrue(isInBackupState(player));
+ }
+
+
+ @Test
+ public void movedPlayerHasChangedCoordinatesTest() {
Vector2 startPosition = new Vector2(player.getPosition().x, player.getPosition().y);
player.setDirection(Direction.EAST);
board.movePlayer(player);
assertNotEquals(startPosition, player.getPosition());
}
+ @Test
+ public void whenPlayerIsMovedUpItHasMovedOneStepTest() {
+ Vector2 startPosition = new Vector2(player.getPosition().x, player.getPosition().y);
+ player.setDirection(Direction.NORTH);
+ board.movePlayer(player);
+ assertEquals((int) startPosition.y+1, (int) player.getPosition().y);
+ }
+
+ @Test
+ public void thereAreHolesOnBoardTest() {
+ assertFalse(holes.isEmpty());
+ }
+
+ @Test
+ public void playerOnRandomHoleIsOutsideBoardTest() {
+ // Choose some random holes
+ for (int i = 0; i < 5; i++) {
+ Vector2 holePosition = getRandomHolePosition();
+ player.setPosition(holePosition);
+ assertTrue(board.outsideBoard(player));
+ }
+ }
+
+ @Test
+ public void playerOnRandomHoleIsRespawnedTest() {
+ // Choose some random holes
+ for (int i = 0; i < 5; i++) {
+ Vector2 holePosition = getRandomHolePosition();
+ player.setPosition(holePosition);
+ board.addPlayer(player);
+ board.respawnPlayers();
+ assertTrue(isInBackupState(player));
+ }
+ }
+
+ @Test
+ public void getWestNeighbourPositionTest() {
+ Vector2 neighbourPosition = new Vector2(startPosition.x -1, startPosition.y);
+ assertEquals(neighbourPosition, board.getNeighbourPosition(startPosition, Direction.WEST));
+ }
+
+ @Test
+ public void getEastNeighbourPositionTest() {
+ Vector2 neighbourPosition = new Vector2(startPosition.x +1, startPosition.y);
+ assertEquals(neighbourPosition, board.getNeighbourPosition(startPosition, Direction.EAST));
+ }
+
+ @Test
+ public void getSouthNeighbourPositionTest() {
+ Vector2 neighbourPosition = new Vector2(startPosition.x, startPosition.y - 1);
+ assertEquals(neighbourPosition, board.getNeighbourPosition(startPosition, Direction.SOUTH));
+ }
+
+ @Test
+ public void getNorthNeighbourPositionTest() {
+ Vector2 neighbourPosition = new Vector2(startPosition.x, startPosition.y + 1);
+ assertEquals(neighbourPosition, board.getNeighbourPosition(startPosition, Direction.NORTH));
+ }
+
+ @Test
+ public void flagIsOnFlagPositionOnBoardTest() {
+ for (int i = 0; i < 5; i++) {
+ Flag flag = getRandomFlag();
+ Vector2 flagPosition = flag.getPosition();
+ assertTrue(board.hasFlag(flagPosition));
+ }
+ }
+
+ @Test
+ public void playerPicksUpFirstFlagTest() {
+ Flag flag = flags.get(0);
+ Vector2 flagPosition = flag.getPosition();
+ player.setPosition(flagPosition);
+ board.pickUpFlag(player);
+ assertTrue(isEqualFlags(flag, player.getFlagsCollected().get(0)));
+ }
+
+ @Test
+ public void canNotPickUpFlagNumberTwoBeforeFlagNumberOneTest() {
+ // Get flag nr. 2
+ Flag flag = flags.get(1);
+ Vector2 flagPosition = flag.getPosition();
+ player.setPosition(flagPosition);
+ board.pickUpFlag(player);
+ assertEquals(0, player.getFlagsCollected().size());
+ }
+
+ @Test
+ public void canNotPickUpFlagNumberThreeBeforeFlagNumberTwoTest() {
+ Flag firstFlag = flags.get(0);
+ player.setPosition(firstFlag.getPosition());
+ board.pickUpFlag(player);
+ Flag thirdFlag = flags.get(2);
+ player.setPosition(thirdFlag.getPosition());
+ board.pickUpFlag(player);
+ assertEquals(1, player.getFlagsCollected().size());
+ }
+
+ @Test
+ public void playerMovesOnFlagTest() {
+ Flag flag = flags.get(0);
+ Vector2 flagPosition = flag.getPosition();
+ Vector2 playerPosition = new Vector2(flagPosition.x -1, flagPosition.y);
+ player.setPosition(playerPosition);
+ player.setDirection(Direction.EAST);
+ board.movePlayer(player);
+ assertTrue(isEqualFlags(flag, player.getFlagsCollected().get(0)));
+ }
+
+ @Test
+ public void pickingUpAllFlagsInIncreasingOrderYouWinTest() {
+ // Visit flags 1, 2, and 3
+ for (int flagNumber = 1; flagNumber <=3; flagNumber++) {
+ Flag flag = flags.get(flagNumber-1);
+ Vector2 flagPosition = flag.getPosition();
+ player.setPosition(flagPosition);
+ board.pickUpFlag(player);
+ }
+ assertTrue(player.hasAllFlags(3));
+ }
+
+ @Test
+ public void facingNeighbourPlayerShouldPushTest() {
+ Vector2 playerToBePushedPosition = new Vector2(0,0);
+ player.setPosition(playerToBePushedPosition);
+ Vector2 playerTwoPos = new Vector2(1, 0);
+ Player player2 = new Player(playerTwoPos, 2);
+ player2.setDirection(Direction.WEST);
+ board.addPlayer(player);
+ assertTrue(board.shouldPush(player2));
+ }
+
+ @Test
+ public void pushedPlayerIsReplacedByPlayerThatIsPushingTest() {
+ Vector2 playerToBePushedPosition = new Vector2(1, 0);
+ player.setPosition(playerToBePushedPosition);
+ Vector2 playerTwoPos = new Vector2(0,0);
+ Player player2 = new Player(playerTwoPos, 2);
+ player2.setDirection(Direction.EAST);
+ board.addPlayer(player);
+ board.movePlayer(player2);
+ assertEquals(player2, board.getPlayer(playerToBePushedPosition));
+ }
+
+ @Test
+ public void pushedPlayerMovesInSameDirectionAsItIsPushedTest() {
+ Vector2 playerToBePushedPosition = new Vector2(1, 0);
+ Vector2 playerIsPushedToPosition = new Vector2(2,0);
+ player.setPosition(playerToBePushedPosition);
+ // Set different direction then it is pushed in
+ player.setDirection(Direction.NORTH);
+ Vector2 playerTwoPos = new Vector2(0,0);
+ Player player2 = new Player(playerTwoPos, 2);
+ player2.setDirection(Direction.EAST);
+ board.addPlayer(player);
+ board.movePlayer(player2);
+ assertEquals(player, board.getPlayer(playerIsPushedToPosition));
+ }
+
+ @Test
+ public void pushingTwoPlayersInSameDirectionTest() {
+ // line 6 from bottom up has no walls in Risky-Exchange:
+ Vector2 playerToBePushedPositionOne = new Vector2(2, 6);
+ Vector2 playerToBePushedPositionTwo = new Vector2(3, 6);
+ Vector2 playerPushingPosition = new Vector2(4, 6);
+ Vector2 positionToBePushedTo = new Vector2(1, 6);
+ Player player2 = new Player(playerToBePushedPositionOne, 2);
+ Player player3 = new Player(playerToBePushedPositionTwo, 3);
+ // Random directions
+ player2.setDirection(Direction.EAST);
+ player3.setDirection(Direction.SOUTH);
+ player.setPosition(playerPushingPosition);
+ player.setDirection(Direction.WEST);
+ board.addPlayer(player2);
+ board.addPlayer(player3);
+ board.movePlayer(player);
+ assertEquals(player2, board.getPlayer(positionToBePushedTo));
+ }
+
+ @Test
+ public void wallStopsPushingTest() {
+ // Found wall in Risky Exhange
+ Vector2 northWallPosition = new Vector2(0, 5);
+ Player player2 = new Player(northWallPosition, 2);
+ player2.setDirection(Direction.WEST);
+ Vector2 playerPushingPosition = new Vector2(0,4);
+ player.setPosition(playerPushingPosition);
+ player.setDirection(Direction.NORTH);
+ board.addPlayer(player2);
+ board.addPlayer(player);
+ board.movePlayer(player);
+ assertEquals(player2, board.getPlayer(northWallPosition));
+ }
+
+ @Test
+ public void wallStopsPushingSeveralPlayersTest() {
+ // Found wall in Risky Exhange
+ Vector2 northWallPosition = new Vector2(0, 5);
+ Vector2 middlePosition = new Vector2(0, 4);
+ Player playerToBeStoppedByWall = new Player(northWallPosition, 2);
+ Player playerInMiddle = new Player(middlePosition, 3);
+ playerToBeStoppedByWall.setDirection(Direction.WEST);
+ playerInMiddle.setDirection(Direction.SOUTH);
+ Vector2 playerPushingPosition = new Vector2(0,3);
+ player.setPosition(playerPushingPosition);
+ player.setDirection(Direction.NORTH);
+ board.addPlayer(playerToBeStoppedByWall);
+ board.addPlayer(playerInMiddle);
+ board.addPlayer(player);
+ board.movePlayer(player);
+ assertEquals(playerToBeStoppedByWall, board.getPlayer(northWallPosition));
+ }
+
}
diff --git a/src/test/java/inf112/skeleton/app/DeckTest.java b/src/test/java/inf112/skeleton/app/DeckTest.java
index 3dd171b2..def5b97e 100644
--- a/src/test/java/inf112/skeleton/app/DeckTest.java
+++ b/src/test/java/inf112/skeleton/app/DeckTest.java
@@ -9,7 +9,6 @@
public class DeckTest {
private Deck deck;
- private final int NUMBER_OF_MOVE_ONE_CARDS = 6;
private final int NUMBER_OF_CARDS = 78;
@Before
@@ -25,15 +24,7 @@ public void whenNewDeckIsMadeTheNumberOfProgramCardsInDeckIsNumberOfCardsTest()
@Test
public void whenNewDeckIsMadeButNotShuffledFirstCardIsAMove1CardTest() {
deck.makeNewDeck();
- assertEquals(1, deck.drawCard().getDistance());
- }
-
- @Test
- public void whenDeckIsNotShuffledTheFirstCardsAreOfTypeMoveOneCardTest() {
- deck.makeNewDeck();
- for (int i = 0; i < NUMBER_OF_MOVE_ONE_CARDS; i++) {
- assertEquals(1, deck.drawCard().getDistance());
- }
+ assertEquals(3, deck.drawCard().getDistance());
}
@Test
diff --git a/src/test/java/inf112/skeleton/app/DirectionTest.java b/src/test/java/inf112/skeleton/app/DirectionTest.java
index 90040375..4465e2d9 100644
--- a/src/test/java/inf112/skeleton/app/DirectionTest.java
+++ b/src/test/java/inf112/skeleton/app/DirectionTest.java
@@ -5,7 +5,6 @@
import org.junit.Test;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
public class DirectionTest {
diff --git a/src/test/java/inf112/skeleton/app/LaserTest.java b/src/test/java/inf112/skeleton/app/LaserTest.java
new file mode 100644
index 00000000..22d361d3
--- /dev/null
+++ b/src/test/java/inf112/skeleton/app/LaserTest.java
@@ -0,0 +1,85 @@
+package inf112.skeleton.app;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.backends.headless.HeadlessApplication;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
+import com.badlogic.gdx.math.Vector2;
+import inf112.skeleton.app.objects.Laser;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+public class LaserTest {
+
+ private RallyGame game;
+ private Board board;
+ private ArrayList lasers;
+
+ @Before
+ public void setUp() {
+ Gdx.gl = mock(GL20.class);
+ //Make a headless application in order to initialize the board. Does not show.
+ new HeadlessApplication(new EmptyApplication());
+ this.game = new RallyGame();
+ this.game.setupGame("assets/maps/Risky_Exchange.tmx");
+ this.board = game.getBoard();
+ this.lasers = board.lasers;
+ }
+
+ /**
+ * @param lasers on board
+ * @return random laser laser from list given
+ */
+ private Laser getRandomLaser(ArrayList lasers) {
+ Random random = new Random();
+ int randomIndex = random.nextInt(lasers.size());
+ return lasers.get(randomIndex);
+ }
+
+ /**
+ * @param position to check for laser
+ * @return true if cell in this position from laserLayer has a laser on this cell.
+ */
+ private boolean hasLaser(Vector2 position) {
+ TiledMapTileLayer laserLayer = board.getLaserLayer();
+ TiledMapTileLayer.Cell cell = laserLayer.getCell((int) position.x, (int) position.y);
+ return cell != null;
+ }
+
+ @Test
+ public void thereAreLasersOnBoardTest() {
+ assertFalse(lasers.isEmpty());
+ }
+
+ @Test
+ public void lasersFiredHasLasersInStartPositionTest() {
+ game.fireLasers();
+ for (int i = 0; i < 3; i++) {
+ Laser laser = getRandomLaser(lasers);
+ Vector2 laserPosition = laser.getStartPosition();
+ assertTrue(hasLaser(laserPosition));
+ }
+ }
+
+ @Test
+ public void playerBlockingLaserTest() {
+ for (int i = 0; i < 3; i++) {
+ Laser laser = getRandomLaser(lasers);
+ Vector2 blockingPosition = board.getNeighbourPosition(laser.getStartPosition(), laser.getDirection());
+ //TODO: Let RallyGame take in number of players as arg
+ Player blockingPlayer = new Player(blockingPosition, 5);
+ board.addPlayer(blockingPlayer);
+ game.fireLasers();
+ Vector2 noLaserPosition = board.getNeighbourPosition(blockingPosition, laser.getDirection());
+ assertFalse(hasLaser(noLaserPosition));
+ }
+ }
+
+}
diff --git a/src/test/java/inf112/skeleton/app/ProgramCardTest.java b/src/test/java/inf112/skeleton/app/ProgramCardTest.java
index 71edb020..4e0e42aa 100644
--- a/src/test/java/inf112/skeleton/app/ProgramCardTest.java
+++ b/src/test/java/inf112/skeleton/app/ProgramCardTest.java
@@ -1,24 +1,154 @@
package inf112.skeleton.app;
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.backends.headless.HeadlessApplication;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.math.Vector2;
+import inf112.skeleton.app.cards.Deck;
import inf112.skeleton.app.cards.ProgramCard;
+import inf112.skeleton.app.enums.Direction;
import inf112.skeleton.app.enums.Rotate;
import org.junit.Before;
import org.junit.Test;
+import java.util.ArrayList;
+
import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
public class ProgramCardTest {
- private ProgramCard card;
+ private Deck deck;
+ private RallyGame game;
+ private Player player;
+ private ProgramCard right;
+ private ProgramCard left;
+ private ProgramCard uturn;
+ private ProgramCard moveOne;
+ private ProgramCard moveTwo;
@Before
public void setUp() {
- card = new ProgramCard(1, 1, Rotate.NONE, "card1");
+ Gdx.gl = mock(GL20.class);
+ //Make a headless application in order to initialize the board. Does not show.
+ new HeadlessApplication(new EmptyApplication());
+ this.game = new RallyGame();
+ this.game.setupGame("assets/maps/Risky_Exchange.tmx");
+
+ // Already 4 players on board.
+ //TODO: Let setupGame take in playerNumber as arg
+ player = new Player(new Vector2(0,0), 5);
+ player.setDirection(Direction.EAST);
+ Board board = game.getBoard();
+ board.addPlayer(player);
+ this.deck = new Deck();
+ this.left = new ProgramCard(10, 0, Rotate.LEFT, "left");
+ this.right = new ProgramCard(10, 0, Rotate.RIGHT, "right");
+ this.uturn = new ProgramCard(10, 0, Rotate.UTURN, "uturn");
+ this.moveOne = new ProgramCard(10, 1, Rotate.NONE, "move 1");
+ this.moveTwo = new ProgramCard(10, 2, Rotate.NONE, "move 2");
+ }
+
+ @Test
+ public void playerGetNineCardsWhenDrawingCardsTest() {
+ player.drawCards(deck);
+ assertEquals(9, player.getAllCards().size());
+ }
+
+ @Test
+ public void canChooseFiveCardsFromDrawnCardsTest() {
+ player.drawCards(deck);
+ player.selectCards();
+ assertEquals(5, player.getSelectedCards().size());
+ }
+
+ @Test
+ public void playingUturnCardTest() {
+ player.setSelectedCards(uturn);
+ game.playCard(player);
+ assertEquals(Direction.WEST, player.getDirection());
+ }
+
+ @Test
+ public void playingRightRotateCardTest() {
+ player.setSelectedCards(right);
+ game.playCard(player);
+ assertEquals(Direction.SOUTH, player.getDirection());
+ }
+
+ @Test
+ public void playingLeftRotateCardTest() {
+ player.setSelectedCards(left);
+ game.playCard(player);
+ assertEquals(Direction.NORTH, player.getDirection());
+ }
+
+ @Test
+ public void playingMoveOneStepCardTest() {
+ player.setSelectedCards(moveOne);
+ Vector2 beforePosition = player.getPosition();
+ Vector2 afterPosition = new Vector2(beforePosition.x + 1, beforePosition.y);
+ game.playCard(player);
+ assertEquals(afterPosition, player.getPosition());
+ }
+
+ @Test
+ public void firstRotateThenMoveToCorrectPositionTest() {
+ player.setSelectedCards(left, moveOne);
+ Vector2 beforePosition = player.getPosition();
+ // Player is rotated left and therefore player will go up instead of to the right
+ Vector2 afterPosition = new Vector2(beforePosition.x, beforePosition.y+1);
+ game.playCard(player);
+ game.playCard(player);
+ assertEquals(afterPosition, player.getPosition());
+ }
+
+ @Test
+ public void firstMoveThenRotateToCorrectRotationTest() {
+ player.setSelectedCards(moveTwo, right);
+ game.playCard(player);
+ game.playCard(player);
+ assertEquals(Direction.SOUTH, player.getDirection());
+ }
+
+ @Test
+ public void prioritizedCardsArePlayedFirstTest() {
+ Player player2 = new Player(new Vector2(0, 1), 6);
+ ProgramCard highPrioCard = new ProgramCard(10, 0, Rotate.LEFT, "left");
+ ProgramCard lowPrioCard = new ProgramCard(1, 0, Rotate.RIGHT, "right");
+ ArrayList players = new ArrayList<>();
+ player.setSelectedCards(lowPrioCard);
+ player2.setSelectedCards(highPrioCard);
+ players.add(player);
+ players.add(player2);
+ players.sort(new PlayerSorter());
+ assertEquals(player2, players.get(0));
+ }
+
+ /**
+ * Starting at east, a sequence of right, left, left, uturn, right, uturn, right should give south.
+ */
+ @Test
+ public void sequenceOfRotateCardsTest() {
+ player.setSelectedCards(right, left, left, uturn, right, uturn, right);
+ for (int playedCards = 0; playedCards <= 6; playedCards++) {
+ game.playCard(player);
+ }
+ assertEquals(Direction.SOUTH, player.getDirection());
}
+ /**
+ * Starting at (0,0) east, move one, rotate left, move two, rotate right, move one, turn around, move two should give
+ * (0, 2)
+ */
@Test
- public void whenRotationIsSetToNoneItHasNoRotationTest() {
- assertEquals(Rotate.NONE, card.getRotate());
+ public void sequenceOfCardsTest() {
+ player.setSelectedCards(moveOne, left, moveTwo, right, moveOne, uturn, moveTwo);
+ Vector2 afterPosition = new Vector2(0,2);
+ for (int playedCards = 0; playedCards <= 6; playedCards++) {
+ game.playCard(player);
+ }
+ assertEquals(afterPosition, player.getPosition());
}
}
diff --git a/src/test/java/inf112/skeleton/app/RotatePadTest.java b/src/test/java/inf112/skeleton/app/RotatePadTest.java
new file mode 100644
index 00000000..06d7ef73
--- /dev/null
+++ b/src/test/java/inf112/skeleton/app/RotatePadTest.java
@@ -0,0 +1,127 @@
+package inf112.skeleton.app;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.backends.headless.HeadlessApplication;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.math.Vector2;
+import inf112.skeleton.app.enums.Direction;
+import inf112.skeleton.app.enums.Rotate;
+import inf112.skeleton.app.objects.RotatePad;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Mockito.mock;
+
+/**
+ * Test right and left rotate-wheels. Can not find any uturn-pads.
+ */
+public class RotatePadTest {
+
+ private RallyGame game;
+ private ArrayList rotatePads;
+ private Player player;
+
+ @Before
+ public void setUp() {
+ Gdx.gl = mock(GL20.class);
+ //Make a headless application in order to initialize the board. Does not show.
+ new HeadlessApplication(new EmptyApplication());
+ this.game = new RallyGame();
+ this.game.setupGame("assets/maps/Risky_Exchange.tmx");
+ Board board = game.getBoard();
+ this.rotatePads = board.rotatePads;
+
+ // Already 4 players on board.
+ //TODO: Let setupGame take in playerNumber as arg
+ player = new Player(new Vector2(0,0), 5);
+ board.addPlayer(player);
+ }
+
+ /**
+ * @return a random rotatePad from the list given
+ */
+ private RotatePad getRandomRotatePad(ArrayList rotatePads) {
+ Random random = new Random();
+ int randomIndex = random.nextInt(rotatePads.size());
+ return rotatePads.get(randomIndex);
+ }
+
+ /**
+ * Get only left rotate pads.
+ *
+ * @param rotatePads on board
+ * @return list of left rotate pads
+ */
+ private ArrayList getLeftRotatePads(ArrayList rotatePads) {
+ ArrayList leftRotatePads = new ArrayList<>();
+ for (RotatePad pad : rotatePads) {
+ if (pad.getRotate() == Rotate.LEFT) {
+ leftRotatePads.add(pad);
+ }
+ }
+ return leftRotatePads;
+ }
+
+ /**
+ * Get only right rotate pads.
+ *
+ * @param rotatePads on board
+ * @return list of right rotate pads
+ */
+ private ArrayList getRightRotatePads(ArrayList rotatePads) {
+ ArrayList rightRotatePads = new ArrayList<>();
+ for (RotatePad pad : rotatePads) {
+ if (pad.getRotate() == Rotate.RIGHT) {
+ rightRotatePads.add(pad);
+ }
+ }
+ return rightRotatePads;
+ }
+
+ @Test
+ public void rotatePadsIsNotEmptyTest() {
+ assertFalse(rotatePads.isEmpty());
+ }
+
+ @Test
+ public void onlyRotateWhenPadIsActivatedTest() {
+ for (int i = 0; i < 3; i++) {
+ RotatePad pad = getRandomRotatePad(rotatePads);
+ player.setDirection(Direction.EAST);
+ player.setPosition(pad.getPosition());
+ assertEquals(Direction.EAST, player.getDirection());
+ }
+ }
+
+ @Test
+ public void playerOnLeftPadRotatesLeftTest() {
+ for (int i = 0; i < 3; i++) {
+ RotatePad pad = getRandomRotatePad(getLeftRotatePads(rotatePads));
+ Vector2 padPosition = pad.getPosition();
+ player.setPosition(padPosition);
+ player.setDirection(Direction.EAST);
+ game.activateRotatePads();
+ assertEquals(Direction.NORTH, player.getDirection());
+ }
+ }
+
+ @Test
+ public void playerOnRightPadRotatesRightTest() {
+ for (int i = 0; i < 3; i++) {
+ RotatePad pad = getRandomRotatePad(getRightRotatePads(rotatePads));
+ Vector2 padPosition = pad.getPosition();
+ player.setPosition(padPosition);
+ player.setDirection(Direction.EAST);
+ game.activateRotatePads();
+ assertEquals(Direction.SOUTH, player.getDirection());
+ }
+ }
+
+
+
+}
diff --git a/src/test/java/inf112/skeleton/app/WallTests.java b/src/test/java/inf112/skeleton/app/WallTests.java
new file mode 100644
index 00000000..2e3df6fa
--- /dev/null
+++ b/src/test/java/inf112/skeleton/app/WallTests.java
@@ -0,0 +1,522 @@
+package inf112.skeleton.app;
+
+import com.badlogic.gdx.Gdx;
+import com.badlogic.gdx.backends.headless.HeadlessApplication;
+import com.badlogic.gdx.graphics.GL20;
+import com.badlogic.gdx.maps.tiled.TiledMapTileLayer;
+import com.badlogic.gdx.math.Vector2;
+import inf112.skeleton.app.enums.Direction;
+import inf112.skeleton.app.enums.TileID;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.mockito.Mockito.mock;
+
+public class WallTests {
+ private Board board;
+ private Player player;
+ private Random random;
+ private ArrayList allNorthWalls;
+ private ArrayList allSouthWalls;
+ private ArrayList allEastWalls;
+ private ArrayList allWestWalls;
+
+ @Before
+ public void setUp() {
+ //Mock OpenGL in order to use gdx.texture, gdx.tmxMapLoader etc without getting
+ // nullpointerexception
+ Gdx.gl = mock(GL20.class);
+ //Make a headless application in order to initialize the board. Does not show.
+ new HeadlessApplication(new EmptyApplication());
+ int NUMBER_OF_PLAYERS_WHEN_STARTING_GAME = 2;
+ this.board = new Board("assets/maps/Risky_Exchange.tmx", NUMBER_OF_PLAYERS_WHEN_STARTING_GAME);
+ this.player = new Player(new Vector2(0,0), 1);
+ random = new Random();
+ allNorthWalls = new ArrayList<>();
+ allSouthWalls = new ArrayList<>();
+ allEastWalls = new ArrayList<>();
+ allWestWalls = new ArrayList<>();
+ putPositionsToWallsInLists();
+ }
+
+ /**
+ *
+ * @param position of tile
+ * @return true if position is on tile before border
+ */
+ private boolean onEastBorder(Vector2 position) {
+ return position.x >= board.getWidth()-1;
+ }
+
+ /**
+ *
+ * @param position of tile
+ * @return true if position is on tile before border
+ */
+ private boolean onWestBorder(Vector2 position) {
+ return position.x < 1;
+ }
+
+ /**
+ *
+ * @param position of tile
+ * @return true if position is on tile before border
+ */
+ private boolean onSouthBorder(Vector2 position) {
+ return position.y < 1;
+ }
+
+ /**
+ *
+ * @param position of tile
+ * @return true if position is on tile before border
+ */
+ private boolean onNorthBorder(Vector2 position) {
+ return position.y >= board.getHeight()-1;
+ }
+
+ /**
+ * @param cell to check
+ * @return true if cell only has north wall
+ */
+ private boolean isOnlyNorthWall(TiledMapTileLayer.Cell cell) {
+ if (cell == null) {
+ return false;
+ }
+ return cell.getTile().getId() == TileID.NORTH_WALL.getId();
+ }
+
+ /**
+ * @param cell to check
+ * @return true if cell only has south wall
+ */
+ private boolean isOnlySouthWall(TiledMapTileLayer.Cell cell) {
+ if (cell == null) {
+ return false;
+ }
+ return cell.getTile().getId() == TileID.SOUTH_WALL.getId();
+ }
+
+ /**
+ * @param cell to check
+ * @return true if cell only has east wall
+ */
+ private boolean isOnlyEastWall(TiledMapTileLayer.Cell cell) {
+ if (cell == null) {
+ return false;
+ }
+ return cell.getTile().getId() == TileID.EAST_WALL.getId();
+ }
+
+ /**
+ * @param cell to check
+ * @return true if cell only has west wall
+ */
+ private boolean isOnlyWestWall(TiledMapTileLayer.Cell cell) {
+ if (cell == null) {
+ return false;
+ }
+ return cell.getTile().getId() == TileID.WEST_WALL.getId();
+ }
+
+ /**
+ * Give a random entry from given list
+ *
+ * @return a random position from the list given
+ */
+ private Vector2 getRandomWallPosition(ArrayList listOfWalls) {
+ int randomIndex = random.nextInt(listOfWalls.size());
+ return listOfWalls.get(randomIndex);
+ }
+
+ /**
+ * Filter out walls like south-east, north-west etc. Is used
+ * so that we can test that a player can move when there is not a wall in
+ * front of the player, but on same tile.
+ *
+ * @param listOfWalls allNorthWalls
+ * @return list of only north walls
+ */
+ private ArrayList getOnlyNorthWalls(ArrayList listOfWalls) {
+ ArrayList northWalls = new ArrayList<>();
+ for (Vector2 wallPos : listOfWalls) {
+ TiledMapTileLayer.Cell cell = board.getWallLayer().getCell((int) wallPos.x, (int) wallPos.y);
+ if (isOnlyNorthWall(cell)) {
+ northWalls.add(wallPos);
+ }
+ }
+ return northWalls;
+ }
+
+ /**
+ * Filter out walls like south-east, north-west etc. Is used
+ * so that we can test that a player can move when there is not a wall in
+ * front of the player, but on same tile.
+ *
+ * @param listOfWalls allSouthWalls
+ * @return list of only south walls
+ */
+ private ArrayList getOnlySouthWalls(ArrayList listOfWalls) {
+ ArrayList southWalls = new ArrayList<>();
+ for (Vector2 wallPos : listOfWalls) {
+ TiledMapTileLayer.Cell cell = board.getWallLayer().getCell((int) wallPos.x, (int) wallPos.y);
+ if (isOnlySouthWall(cell)) {
+ southWalls.add(wallPos);
+ }
+ }
+ return southWalls;
+ }
+
+ /**
+ * Filter out walls like south-east, north-west etc. Is used
+ * so that we can test that a player can move when there is not a wall in
+ * front of the player, but on same tile.
+ *
+ * @param listOfWalls allEastWalls
+ * @return list of only east walls
+ */
+ private ArrayList getOnlyEastWalls(ArrayList listOfWalls) {
+ ArrayList eastWalls = new ArrayList<>();
+ for (Vector2 wallPos : listOfWalls) {
+ TiledMapTileLayer.Cell cell = board.getWallLayer().getCell((int) wallPos.x, (int) wallPos.y);
+ if (isOnlyEastWall(cell)) {
+ eastWalls.add(wallPos);
+ }
+ }
+ return eastWalls;
+ }
+
+ /**
+ * Filter out walls like south-east, north-west etc. Is used
+ * so that we can test that a player can move when there is not a wall in
+ * front of the player, but on same tile.
+ *
+ * @param listOfWalls allWestWalls
+ * @return list of only west walls
+ */
+ private ArrayList getOnlyWestWalls(ArrayList listOfWalls) {
+ ArrayList westWalls = new ArrayList<>();
+ for (Vector2 wallPos : listOfWalls) {
+ TiledMapTileLayer.Cell cell = board.getWallLayer().getCell((int) wallPos.x, (int) wallPos.y);
+ if (isOnlyWestWall(cell)) {
+ westWalls.add(wallPos);
+ }
+ }
+ return westWalls;
+ }
+
+ /**
+ * In order to test that a player can not move when facing a wall on a neighbour cell,
+ * player needs to be placed on the cell next to the wall. Then this cell can not have a wall
+ * facing towards the border, because then the player will be placed outside the board.
+ *
+ * @param listOfWalls a list of position to the walls
+ * @return a list of position for the walls, where the walls aligning the borderline is excluded
+ */
+ private ArrayList filterWallsOnBorder(ArrayList listOfWalls) {
+ ArrayList wallsCopy = (ArrayList) listOfWalls.clone();
+ for (Vector2 wallPosition : listOfWalls) {
+ TiledMapTileLayer.Cell wallCell = board.getWallLayer().getCell((int) wallPosition.x, (int) wallPosition.y);
+ if (onEastBorder(wallPosition) && board.hasEastWall(wallCell)) {
+ wallsCopy.remove(wallPosition);
+ }
+ if (onSouthBorder(wallPosition) && board.hasSouthWall(wallCell)) {
+ wallsCopy.remove(wallPosition);
+ }
+ if (onWestBorder((wallPosition)) && board.hasWestWall(wallCell)) {
+ wallsCopy.remove(wallPosition);
+ }
+ if (onNorthBorder(wallPosition) && board.hasNorthWall(wallCell)) {
+ wallsCopy.remove(wallPosition);
+ }
+ }
+ return wallsCopy;
+ }
+
+ /**
+ * Put all position to the walls on board in lists.
+ */
+ private void putPositionsToWallsInLists() {
+ TiledMapTileLayer wallLayer = board.getWallLayer();
+ for (int x = 0; x < board.getWidth(); x++) {
+ for (int y = 0; y < board.getHeight(); y++) {
+ Vector2 pos = new Vector2(x, y);
+ TiledMapTileLayer.Cell wall = wallLayer.getCell(x, y);
+ if (board.hasSouthWall(wall)) {
+ allSouthWalls.add(pos);
+ }
+ if (board.hasNorthWall(wall)) {
+ allNorthWalls.add(pos);
+ }
+ if (board.hasEastWall(wall)) {
+ allEastWalls.add(pos);
+ }
+ if (board.hasWestWall(wall)) {
+ allWestWalls.add(pos);
+ }
+ }
+ }
+ }
+
+ @Test
+ public void thereAreNorthWallsOnBoardTest() {
+ assertFalse(allNorthWalls.isEmpty());
+ }
+
+ @Test
+ public void thereAreSouthWallsOnBoardTest() {
+ assertFalse(allSouthWalls.isEmpty());
+ }
+
+ @Test
+ public void thereAreEastWallsOnBoardTest() {
+ assertFalse(allEastWalls.isEmpty());
+ }
+
+ @Test
+ public void thereAreWestWallsOnBoardTest() {
+ assertFalse(allWestWalls.isEmpty());
+ }
+
+
+ @Test
+ public void playerIsOnCellWithNorthWallTest() {
+ // Found position in Risky_Exchange.tmx, North Wall has ID 31
+ player.setPosition(new Vector2(2, 0));
+ TiledMapTileLayer wallLayer = board.getWallLayer();
+ TiledMapTileLayer.Cell playerCell = wallLayer.getCell((int) player.getPosition().x, (int) player.getPosition().y);
+ assertTrue(board.hasNorthWall(playerCell));
+ }
+
+ @Test
+ public void playerIsOnCellWithWestWallTest() {
+ // Found position in Risky_Exchange.tmx, SouthWest wall has ID 32
+ player.setPosition(new Vector2(11, 7));
+ TiledMapTileLayer wallLayer = board.getWallLayer();
+ TiledMapTileLayer.Cell playerCell = wallLayer.getCell((int) player.getPosition().x, (int) player.getPosition().y);
+ assertTrue(board.hasWestWall(playerCell));
+ }
+
+ @Test
+ public void playerIsOnCellWithEastWallTestTest() {
+ // Found position in Risky_Exchange.tmx, East Wall ha ID 23
+ player.setPosition(new Vector2(3, 2));
+ TiledMapTileLayer wallLayer = board.getWallLayer();
+ TiledMapTileLayer.Cell playerCell = wallLayer.getCell((int) player.getPosition().x, (int) player.getPosition().y);
+ assertTrue(board.hasEastWall(playerCell));
+ }
+
+ @Test
+ public void playerFacingRandomNorthWallCanNotGoTest() {
+ // Test for some random walls on board
+ for (int i = 0; i < 5; i++) {
+ assertFalse(board.canGo(getRandomWallPosition(allNorthWalls), Direction.NORTH));
+ }
+ }
+
+ @Test
+ public void playerFacingRandomEastWallCanNotGoTest() {
+ // Test for some random walls on board
+ for (int i = 0; i < 5; i++) {
+ assertFalse(board.canGo(getRandomWallPosition(allEastWalls), Direction.EAST));
+ }
+ }
+
+ @Test
+ public void playerFacingRandomSouthWallCanNotGoTest() {
+ // Test for some random walls on board
+ for (int i = 0; i < 5; i++) {
+ assertFalse(board.canGo(getRandomWallPosition(allSouthWalls), Direction.SOUTH));
+ }
+ }
+
+ @Test
+ public void playerFacingRandomWestWallCanNotGoTest() {
+ // Test for some random walls on board
+ for (int i = 0; i < 5; i++) {
+ assertFalse(board.canGo(getRandomWallPosition(allWestWalls), Direction.WEST));
+ }
+ }
+
+ @Test
+ public void playerFacingRandomNorthWallDoesNotMoveTest() {
+ // Test for some random walls
+ for (int i = 0; i < 5; i++) {
+ player.setPosition(getRandomWallPosition(allNorthWalls));
+ player.setDirection(Direction.NORTH);
+ Vector2 posBefore = new Vector2((int) player.getPosition().x, (int) player.getPosition().y);
+ board.movePlayer(player);
+ assertEquals(posBefore, player.getPosition());
+ }
+ }
+
+ @Test
+ public void playerFacingRandomSouthWallDoesNotMoveTest() {
+ // Test for some random walls
+ for (int i = 0; i < 5; i++) {
+ player.setPosition(getRandomWallPosition(allSouthWalls));
+ player.setDirection(Direction.SOUTH);
+ Vector2 posBefore = new Vector2((int) player.getPosition().x, (int) player.getPosition().y);
+ board.movePlayer(player);
+ assertEquals(posBefore, player.getPosition());
+ }
+ }
+
+ @Test
+ public void playerFacingRandomEastWallDoesNotMoveTest() {
+ // Test for several random walls
+ for (int i = 0; i < 5; i++) {
+ player.setPosition(getRandomWallPosition(allEastWalls));
+ player.setDirection(Direction.EAST);
+ Vector2 posBefore = new Vector2((int) player.getPosition().x, (int) player.getPosition().y);
+ board.movePlayer(player);
+ assertEquals(posBefore, player.getPosition());
+ }
+ }
+
+ @Test
+ public void playerFacingRandomWestWallDoesNotMoveTest() {
+ // Test for several random walls
+ for (int i = 0; i < 5; i++) {
+ player.setPosition(getRandomWallPosition(allWestWalls));
+ player.setDirection(Direction.WEST);
+ Vector2 posBefore = new Vector2((int) player.getPosition().x, (int) player.getPosition().y);
+ board.movePlayer(player);
+ assertEquals(posBefore, player.getPosition());
+ }
+ }
+
+ @Test
+ public void playerIsNotFacingRandomNorthWallButOnSameTileAsWallThenPlayerCanMoveTest() {
+ // Test for several random walls
+ for (int i = 0; i < 5; i++) {
+ player.setPosition(getRandomWallPosition(getOnlyNorthWalls(allNorthWalls)));
+ player.setDirection(Direction.WEST);
+ Vector2 posBefore = new Vector2((int) player.getPosition().x, (int) player.getPosition().y);
+ board.movePlayer(player);
+ assertNotEquals(posBefore, player.getPosition());
+ }
+ }
+
+ @Test
+ public void playerIsNotFacingRandomWestWallButOnSameTileAsWallThenPlayerCanMoveTest() {
+ // Test for several random walls
+ for (int i = 0; i < 5; i++) {
+ player.setPosition(getRandomWallPosition(getOnlyWestWalls(allWestWalls)));
+ player.setDirection(Direction.EAST);
+ Vector2 posBefore = new Vector2((int) player.getPosition().x, (int) player.getPosition().y);
+ board.movePlayer(player);
+ assertNotEquals(posBefore, player.getPosition());
+ }
+ }
+
+ @Test
+ public void playerIsNotFacingRandomEastWallButOnSameTileAsWallThenPlayerCanMoveTest() {
+ // Test for several random walls
+ for (int i = 0; i < 5; i++) {
+ player.setPosition(getRandomWallPosition(getOnlyEastWalls(allEastWalls)));
+ player.setDirection(Direction.SOUTH);
+ Vector2 posBefore = new Vector2((int) player.getPosition().x, (int) player.getPosition().y);
+ board.movePlayer(player);
+ assertNotEquals(posBefore, player.getPosition());
+ }
+ }
+
+ @Test
+ public void playerIsNotFacingRandomSouthWallButOnSameTileAsWallThenPlayerCanMoveTest() {
+ // Test for several random walls
+ for (int i = 0; i < 5; i++) {
+ player.setPosition(getRandomWallPosition(getOnlySouthWalls(allSouthWalls)));
+ player.setDirection(Direction.NORTH);
+ Vector2 posBefore = new Vector2((int) player.getPosition().x, (int) player.getPosition().y);
+ board.movePlayer(player);
+ assertNotEquals(posBefore, player.getPosition());
+ }
+ }
+
+ /**
+ * A player can be on tile with no walls but still
+ * have a neighbouring tile with wall pointing against
+ * player. So when a player tries to go on this tile, it should
+ * be blocked even though it has no wall on the tile player is standing
+ * on.
+ */
+ @Test
+ public void playerFacingRandomEastWallOnNeighbourCellCanNotMoveTest() {
+ // Test for some random walls
+ for (int i = 0; i < 5; i++) {
+ Vector2 neighbourCellWithWall = getRandomWallPosition(filterWallsOnBorder(allEastWalls));
+ int neighbourX = (int) neighbourCellWithWall.x;
+ int neighbourY = (int) neighbourCellWithWall.y;
+ Vector2 playerPosition = new Vector2(neighbourX + 1, neighbourY);
+ player.setPosition(playerPosition);
+ player.setDirection(Direction.WEST);
+ board.movePlayer(player);
+ assertEquals(playerPosition, player.getPosition());
+ }
+ }
+
+ /**
+ * See {@link #playerFacingRandomEastWallOnNeighbourCellCanNotMoveTest()}
+ */
+ @Test
+ public void playerFacingRandomWestWallOnNeighbourCellCanNotMoveTest() {
+ // Test for some random walls
+ for (int i = 0; i < 5; i++) {
+ Vector2 neighbourCellWithWall = getRandomWallPosition(filterWallsOnBorder(allWestWalls));
+ int neighbourX = (int) neighbourCellWithWall.x;
+ int neighbourY = (int) neighbourCellWithWall.y;
+ Vector2 playerPosition = new Vector2(neighbourX - 1, neighbourY);
+ player.setPosition(playerPosition);
+ player.setDirection(Direction.EAST);
+ board.movePlayer(player);
+ assertEquals(playerPosition, player.getPosition());
+ }
+ }
+
+ /**
+ * See {@link #playerFacingRandomEastWallOnNeighbourCellCanNotMoveTest()}
+ */
+ @Test
+ public void playerFacingRandomNorthWallOnNeighbourCellCanNotMoveTest() {
+ // Test for some random walls
+ for (int i = 0; i < 5; i++) {
+ Vector2 neighbourCellWithWall = getRandomWallPosition(filterWallsOnBorder(allNorthWalls));
+ int neighbourX = (int) neighbourCellWithWall.x;
+ int neighbourY = (int) neighbourCellWithWall.y;
+ Vector2 playerPosition = new Vector2(neighbourX, neighbourY+1);
+ player.setPosition(playerPosition);
+ player.setDirection(Direction.SOUTH);
+ board.movePlayer(player);
+ assertEquals(playerPosition, player.getPosition());
+ }
+ }
+
+ /**
+ * See {@link #playerFacingRandomEastWallOnNeighbourCellCanNotMoveTest()}
+ */
+ @Test
+ public void playerFacingRandomSouthWallOnNeighbourCellCanNotMoveTest() {
+ // Test for some random walls
+ for (int i = 0; i < 5; i++) {
+ Vector2 neighbourCellWithWall = getRandomWallPosition(filterWallsOnBorder(allSouthWalls));
+ int neighbourX = (int) neighbourCellWithWall.x;
+ int neighbourY = (int) neighbourCellWithWall.y;
+ Vector2 playerPosition = new Vector2(neighbourX, neighbourY-1);
+ player.setPosition(playerPosition);
+ player.setDirection(Direction.NORTH);
+ board.movePlayer(player);
+ assertEquals(playerPosition, player.getPosition());
+ }
+ }
+
+
+
+}