Skip to content
Snippets Groups Projects
Commit b3a8d361 authored by BOVO Pascal's avatar BOVO Pascal
Browse files

Ajout du simulateur (sources)

parent 6098d78d
No related branches found
No related tags found
No related merge requests found
Showing
with 1131 additions and 4 deletions
#include "Display.h"
#include <SDL2/SDL_image.h>
#include <iostream>
const char* chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&/*()-_+=: ";
Display::Display(Solution *p_solution) : window(nullptr), renderer(nullptr), background(nullptr) {
_sol = p_solution;
}
bool Display::init(const std::string& title) {
int width = backgroundWidth+actionsColWidth;
int height = backgroundHeight+buttonsSize;
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cerr << "Failed to initialize SDL: " << SDL_GetError() << std::endl;
return false;
}
window = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, width, height, SDL_WINDOW_SHOWN);
if (!window) {
std::cerr << "Failed to create window: " << SDL_GetError() << std::endl;
return false;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
if (!renderer) {
std::cerr << "Failed to create renderer: " << SDL_GetError() << std::endl;
return false;
}
// Load the background texture
background = loadTexture("assets/background.png");
if (!background) {
std::cerr << "Failed to load background texture" << std::endl;
return false;
}
perso = loadTexture("assets/Perso.png");
if (!perso) {
std::cerr << "Failed to load perso texture" << std::endl;
return false;
}
play = loadTexture("assets/Play.png");
if (!perso) {
std::cerr << "Failed to load play texture" << std::endl;
return false;
}
pause = loadTexture("assets/Pause.png");
if (!perso) {
std::cerr << "Failed to load pause texture" << std::endl;
return false;
}
reload = loadTexture("assets/Reload.png");
if (!reload) {
std::cerr << "Failed to load reload texture" << std::endl;
return false;
}
slider = { buttonsSize*3, backgroundHeight, backgroundWidth - (buttonsSize*3 + nbWidth*2), buttonsSize, 20, 0, false }; // x, y, width, height, handleWidth, initial value
font24Map = loadTexture("assets/Courier_New24.bmp");
if (!font24Map) {
std::cerr << "Failed to load font texture" << std::endl;
return false;
}
SDL_QueryTexture(font24Map, NULL, NULL, &font24Width, &font24Height);
font24Width /= strlen(chars);
font18Map = loadTexture("assets/Courier_New18.bmp");
if (!font18Map) {
std::cerr << "Failed to load font texture" << std::endl;
return false;
}
SDL_QueryTexture(font18Map, NULL, NULL, &font18Width, &font18Height);
font18Width /= strlen(chars);
return true;
}
SDL_Texture* Display::loadTexture(const std::string& path) {
SDL_Texture* texture = IMG_LoadTexture(renderer, path.c_str());
if (!texture) {
std::cerr << "Failed to load texture: " << IMG_GetError() << std::endl;
}
return texture;
}
void Display::render(const Solution& solution) {
if (playing){
if ((clock() - lastFrame) > CLOCKS_PER_SEC*0.3){
_sol->setCurrentStateIndex(_sol->getCurrentStateIndex()+1);
if (_sol->getCurrentStateIndex() > _sol->getNbStates() - 1){
playing = false;
}
lastFrame = clock();
}
}
SDL_SetRenderDrawColor(renderer, 200, 200, 200, 255); // default color
SDL_RenderClear(renderer);
// Render background
SDL_Rect backgroundDest = {.x=0, .y=0, .w=backgroundWidth, .h=backgroundHeight};
SDL_RenderCopy(renderer, background, nullptr, &backgroundDest);
//RenderButtons
SDL_Rect reloadDest = {.x=0, .y=backgroundHeight, .w=buttonsSize, .h=buttonsSize};
SDL_RenderCopy(renderer, reload, nullptr, &reloadDest);
SDL_Rect playDest = {.x=buttonsSize, .y=backgroundHeight, .w=buttonsSize, .h=buttonsSize};
SDL_RenderCopy(renderer, play, nullptr, &playDest);
SDL_Rect pauseDest = {.x=buttonsSize+buttonsSize, .y=backgroundHeight, .w=buttonsSize, .h=buttonsSize};
SDL_RenderCopy(renderer, pause, nullptr, &pauseDest);
renderSlider();
SDL_Rect frameNbRect = {.x=backgroundWidth-(nbWidth*2), .y=backgroundHeight, .w=buttonsSize, .h=buttonsSize};
renderText(" "+std::to_string(_sol->getCurrentStateIndex()), frameNbRect, 24);
SDL_Rect totFrameNbRect = {.x=backgroundWidth-nbWidth, .y=backgroundHeight, .w=buttonsSize, .h=buttonsSize};
renderText("/" + std::to_string(_sol->getNbStates()), totFrameNbRect, 24);
// Render Perso
renderPerso();
renderActions();
// Render game elements according to the current action in the solution
// For example, use SDL_RenderCopy to display moving objects
// based on the current action in the solution
SDL_RenderPresent(renderer);
}
void Display::renderPerso(){
Solution::Point_t gridPos = _sol->getCurrentPos();
int fullImgPosY = ((gridPos.y)/(gridHeight-1.) * (bottomLefty - topLefty)) + topLefty;
int topx = ((gridPos.x)/(gridWidth-1.) * (topRightx - topLeftx)) + topLeftx;
int bottomx = ((gridPos.x)/(gridWidth-1.) * (bottomRightx - bottomLeftx)) + bottomLeftx;
int fullImgPosX = topx * (1-((gridPos.y)/(gridWidth-1.))) + bottomx * (gridPos.y)/(gridWidth-1.);
SDL_Rect persoDest = {.x=fullImgPosX - (persoWidth/2), .y=fullImgPosY - (persoHeight/2), .w=persoWidth, .h=persoHeight};
SDL_RenderCopy(renderer, perso, nullptr, &persoDest);
}
// Function to render the slider
void Display::renderSlider() {
Uint8 r, g, b, a;
SDL_GetRenderDrawColor(renderer, &r, &g, &b, &a);
slider.value = ((float)_sol->getCurrentStateIndex()) / _sol->getNbStates();
// Draw the slider track
SDL_SetRenderDrawColor(renderer, 100, 100, 100, 255); // Track color
SDL_Rect track = { slider.x, slider.y + (slider.height / 2) - 5, slider.width, 10 };
SDL_RenderFillRect(renderer, &track);
// Calculate the position of the handle based on the value
int handleX = slider.x + (slider.value * (slider.width - slider.handleWidth));
// Draw the slider handle
if (!slider.dragging){
SDL_SetRenderDrawColor(renderer, 50, 50, 50, 255); // Handle color
} else {
SDL_SetRenderDrawColor(renderer, 150, 150, 150, 255); // Handle color
}
SDL_Rect handle = { handleX, slider.y, slider.handleWidth, slider.height };
SDL_RenderFillRect(renderer, &handle);
SDL_SetRenderDrawColor(renderer, r, g, b, a); // default color
}
// Function to render text in the text box
void Display::renderText(const std::string& text, SDL_Rect& rect, int size) {
SDL_Texture* fontMap;
int fontWidth;
int fontHeight;
if (size == 18){
fontMap = font18Map;
fontWidth = font18Width;
fontHeight = font18Height;
} else {
fontMap = font24Map;
fontWidth = font24Width;
fontHeight = font24Height;
}
SDL_Rect cursor = {.x=rect.x, .y=rect.y, .w=fontWidth, .h=fontHeight};
SDL_Rect character = {.x=0, .y=0, .w=fontWidth, .h=fontHeight};
const char* ctext = text.c_str();
for (int i = 0 ; i<strlen(ctext) ; i++){
if (ctext[i] =='\n'){
cursor.x = rect.x;
cursor.y += fontHeight;
continue;
}
character.x = ((int)(strchr(chars, ctext[i])-chars))*fontWidth;
SDL_RenderCopy(renderer, fontMap, &character, &cursor);
cursor.x += fontWidth;
if ((ctext[i] == ' ') && (i != strlen(ctext-1))){
char* nextSpace = strchr((char*)ctext+i+1, ' ');
char* nextNewline = strchr((char*)ctext+i+1, '\n');
if (nextNewline){
if (nextSpace){
if (nextNewline < nextSpace){
nextSpace = nextNewline;
}
} else {
nextSpace = nextNewline;
}
}
int distToNextSpace = 0;
if (nextSpace){
distToNextSpace = nextSpace - (ctext+i);
} else {
distToNextSpace = strlen(ctext+i);
}
if (cursor.x + (distToNextSpace * fontWidth) > rect.x + rect.w){
cursor.x = rect.x;
cursor.y += fontHeight;
}
}
}
rect.h = cursor.y + fontHeight - rect.y;
}
void Display::measureText(const std::string& text, SDL_Rect& rect, int size) {
SDL_Texture* fontMap;
int fontWidth;
int fontHeight;
if (size == 18){
fontMap = font18Map;
fontWidth = font18Width;
fontHeight = font18Height;
} else {
fontMap = font24Map;
fontWidth = font24Width;
fontHeight = font24Height;
}
SDL_Rect cursor = {.x=rect.x, .y=rect.y, .w=fontWidth, .h=fontHeight};
const char* ctext = text.c_str();
for (int i = 0 ; i<strlen(ctext) ; i++){
if (ctext[i] =='\n'){
cursor.x = rect.x;
cursor.y += fontHeight;
continue;
}
cursor.x += fontWidth;
if ((ctext[i] == ' ') && (i != strlen(ctext-1))){
char* nextSpace = strchr((char*)ctext+i+1, ' ');
char* nextNewline = strchr((char*)ctext+i+1, '\n');
if (nextNewline){
if (nextSpace){
if (nextNewline < nextSpace){
nextSpace = nextNewline;
}
} else {
nextSpace = nextNewline;
}
}
int distToNextSpace = 0;
if (nextSpace){
distToNextSpace = nextSpace - (ctext+i);
} else {
distToNextSpace = strlen(ctext+i);
}
if (cursor.x + (distToNextSpace * fontWidth) > rect.x + rect.w){
cursor.x = rect.x;
cursor.y += fontHeight;
}
}
}
rect.h = cursor.y + fontHeight - rect.y;
}
void Display::renderActions(){
actionsEndHeight.clear();
std::vector<std::string> actions = _sol->getActionsStrings();
SDL_Rect currentCell = {.x=backgroundWidth, .y=-actionsScroll, .w=actionsColWidth, .h=500};
for (int i = 0;i<actions.size();i++){
measureText(actions[i], currentCell, 18);
if (i == _sol->getCurrentStateIndex()-1){
SDL_SetRenderDrawColor(renderer, 0, 255, 255, 255);
} else {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
}
SDL_RenderFillRect(renderer, &currentCell);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderDrawRect(renderer, &currentCell);
renderText(actions[i], currentCell, 18);
currentCell.y += currentCell.h;
actionsEndHeight.push_back(currentCell.y);
}
actionsTotalHeight = currentCell.y + actionsScroll;
}
void Display::handleEvents(bool& running) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = false;
}
if (event.type == SDL_MOUSEBUTTONDOWN) {
if (event.button.button == SDL_BUTTON_LEFT) {
int mouseX = event.button.x;
int mouseY = event.button.y;
// Check if the mouse is on the handle
int handleX = slider.x + (slider.value * (slider.width - slider.handleWidth));
//if (mouseX >= handleX && mouseX <= handleX + slider.handleWidth &&
if (mouseX >= slider.x && mouseX <= slider.x + slider.width &&
mouseY >= slider.y && mouseY <= slider.y + slider.height)
{
slider.dragging = true;
playing = false;
slider.value = (mouseX - slider.x) * 1. / (slider.width);
_sol->setCurrentStateIndex(round(_sol->getNbStates() * slider.value));
}
// Check if the mouse is on the Actions tab
if (mouseX > backgroundWidth){
//Find correct action
for (int i = 0;i<_sol->getNbActions();i++){
if (mouseY < actionsEndHeight[i]){
_sol->setCurrentStateIndex(i+1);
break;
}
}
}
// Check buttons
if (mouseY > backgroundHeight){
if (mouseX < buttonsSize){
_sol->load();
playing = false;
} else if (mouseX < 2*buttonsSize){
playing = true;
lastFrame = clock();
} else if (mouseX < 3*buttonsSize){
playing = false;
}
}
}
}
if (event.type == SDL_MOUSEBUTTONUP) {
if (event.button.button == SDL_BUTTON_LEFT) {
slider.dragging = false;
}
}
if (event.type == SDL_MOUSEMOTION && slider.dragging) {
int mouseX = event.motion.x;
// Update the slider value based on mouse position
if (mouseX < slider.x) {
slider.value = 0;
} else if (mouseX > slider.x + slider.width) {
slider.value = 1;
} else {
slider.value = (mouseX - slider.x) * 1. / (slider.width);
}
_sol->setCurrentStateIndex(round(_sol->getNbStates() * slider.value));
}
if (event.type == SDL_MOUSEWHEEL ){
actionsScroll -= event.wheel.y * 20;
if (actionsScroll > actionsTotalHeight - (backgroundHeight+buttonsSize)){
actionsScroll = (actionsTotalHeight - (backgroundHeight+buttonsSize));
}
if (actionsScroll < 0){
actionsScroll = 0;
}
}
// Handle other events like play/pause, progress bar, etc.
}
}
void Display::cleanup() {
SDL_DestroyTexture(background);
SDL_DestroyTexture(perso);
SDL_DestroyTexture(play);
SDL_DestroyTexture(pause);
SDL_DestroyTexture(reload);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}
\ No newline at end of file
#ifndef DISPLAY_H
#define DISPLAY_H
#include "Solution.h"
#include <SDL2/SDL.h>
#include <string>
class Display {
// Slider structure
struct Slider {
int x, y; // Position of the slider
int width, height; // Dimensions of the slider track
int handleWidth; // Width of the slider handle
float value; // Current value of the slider (0 to 1)
bool dragging; // Is the slider handle being dragged?
};
public:
Display(Solution *p_solution);
bool init(const std::string& title);
void render(const Solution& solution);
void handleEvents(bool& running);
void cleanup();
private:
// Add textures for game elements
SDL_Texture* loadTexture(const std::string& path);
void renderSlider();
void renderText(const std::string& text, SDL_Rect& rect, int size);
void measureText(const std::string& text, SDL_Rect& rect, int size);
void renderActions();
void renderPerso();
private:
Solution *_sol;
SDL_Window* window;
SDL_Renderer* renderer;
SDL_Texture* background;
SDL_Texture* perso;
SDL_Texture* play;
SDL_Texture* pause;
SDL_Texture* reload;
bool playing = false;
unsigned long lastFrame = 0;
Slider slider;
SDL_Texture* font24Map;
int font24Width;
int font24Height;
SDL_Texture* font18Map;
int font18Width;
int font18Height;
std::vector<int> actionsEndHeight;
int actionsScroll = 0;
int actionsTotalHeight = 0;
const int backgroundWidth = 1265;
const int backgroundHeight = 784;
const int persoWidth = 109;
const int persoHeight = 101;
const int actionsColWidth = 200;
const int buttonsSize = 28;
const int nbWidth = 4*16;
const int topLeftx = 296;
const int topLefty = 184;
const int topRightx = 935;
const int topRighty = 184;
const int bottomLeftx = 220;
const int bottomLefty = 580;
const int bottomRightx = 1002;
const int bottomRighty = 580;
//grille 11*7
const int gridWidth = 11;
const int gridHeight = 7;
};
#endif // DISPLAY_H
#include <SDL.h>
#include <SDL_ttf.h>
#include <iostream>
#include <unordered_map>
#include <string>
// Bitmap font structure
struct BitmapFont {
SDL_Surface* surface; // The surface containing all characters
std::unordered_map<char, SDL_Rect> charRects; // Map of character positions in the atlas
int fontHeight; // Height of the font
};
// Function to create a bitmap font surface from a TTF font and save as BMP
BitmapFont createBitmapFont(TTF_Font* font, const std::string& characters, const std::string& bmpFilename) {
BitmapFont bitmapFont;
bitmapFont.fontHeight = TTF_FontHeight(font);
int padding = 0; // Padding between characters
int textureWidth = 512; // Width of the texture atlas
int textureHeight = bitmapFont.fontHeight + padding * 2; // Height will adjust
// Calculate the width required for all characters
int currentX = padding;
int maxHeight = bitmapFont.fontHeight + padding * 2;
int maxWidth = 0;
int nbChars = 0;
for (char c : characters) {
int charWidth;
TTF_GlyphMetrics(font, c, nullptr, nullptr, nullptr, nullptr, &charWidth);
currentX += charWidth + padding;
if (charWidth > maxWidth){
maxWidth = charWidth;
}
nbChars++;
}
// Create an SDL surface to hold the bitmap font
textureHeight = maxHeight;
textureWidth = maxWidth*nbChars;
SDL_Surface* surface = SDL_CreateRGBSurface(0, textureWidth, textureHeight, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
if (!surface) {
std::cerr << "Failed to create surface: " << SDL_GetError() << std::endl;
exit(1);
}
// Now render each character to the surface
currentX = 0;
SDL_Color black = { 0, 0, 0, 255 };
for (char c : characters) {
SDL_Surface* glyphSurface = TTF_RenderGlyph_Blended(font, c, black); // Render character in black
if (!glyphSurface) {
std::cerr << "Failed to render glyph: " << SDL_GetError() << std::endl;
continue;
}
// Get the size of the glyph
int charWidth = glyphSurface->w;
int charHeight = glyphSurface->h;
// Set character position in the surface
SDL_Rect srcRect = { 0, 0, charWidth, charHeight };
SDL_Rect destRect = { currentX, padding, charWidth, charHeight };
SDL_BlitSurface(glyphSurface, &srcRect, surface, &destRect);
// Store the rectangle for this character
bitmapFont.charRects[c] = destRect;
currentX += maxWidth;
// Clean up the temporary surface
SDL_FreeSurface(glyphSurface);
}
// Save the surface as a BMP file
if (SDL_SaveBMP(surface, bmpFilename.c_str()) != 0) {
std::cerr << "Failed to save BMP: " << SDL_GetError() << std::endl;
} else {
std::cout << "Bitmap font saved as " << bmpFilename << std::endl;
}
bitmapFont.surface = surface;
return bitmapFont;
}
void generateSize(int size){
// Load a font
TTF_Font* font = TTF_OpenFont("assets/Courier_New.ttf", size); // Adjust the font size and path
if (!font) {
std::cerr << "Failed to load font: " << TTF_GetError() << std::endl;
TTF_Quit();
SDL_Quit();
exit(-1);
}
// Characters to include in the bitmap font
std::string characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&/*()-_+=: ";
// Create the bitmap font and save it as a BMP
std::string bmpFilename = "assets/Courier_New" + std::to_string(size) + ".bmp";
BitmapFont bitmapFont = createBitmapFont(font, characters, bmpFilename);
// Clean up
SDL_FreeSurface(bitmapFont.surface);
TTF_CloseFont(font);
}
int main() {
// Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
return -1;
}
// Initialize SDL_ttf
if (TTF_Init() == -1) {
std::cerr << "TTF_Init failed: " << TTF_GetError() << std::endl;
SDL_Quit();
return -1;
}
generateSize(24);
generateSize(18);
TTF_Quit();
SDL_Quit();
return 0;
}
CXX=g++
CXXFLAGS=-Wall -Wextra `sdl2-config --cflags`
LDFLAGS=`sdl2-config --libs` -lSDL2_image -lstdc++
overcooked: main.o Solution.o Display.o
$(CXX) $(CXXFLAGS) main.o Solution.o Display.o -o overcooked $(LDFLAGS)
Solution.o:Solution.cpp Solution.h
$(CXX) $(CXXFLAGS) Solution.cpp -c $(LDFLAGS)
Display.o:Display.cpp Display.h
$(CXX) $(CXXFLAGS) Display.cpp -c $(LDFLAGS)
main.o: main.cpp Display.h Solution.h
$(CXX) $(CXXFLAGS) main.cpp -c $(LDFLAGS)
GenerateBitmapFont: GenerateBitmapFont.c
$(CXX) $(CXXFLAGS) GenerateBitmapFont.c -o GenerateBitmapFont $(LDFLAGS) -lSDL2_ttf
assets/Courier_New24.bmp: GenerateBitmapFont assets/Courier_New.ttf
./GenerateBitmapFont
clean:
rm -rf *.o overcooked GenerateBitmapFont
\ No newline at end of file
#include "Solution.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <algorithm>
Solution::Solution(char* filename)
{
_file_location = filename;
_states.push_back((State_t){.pos=_coordinatesOfLocation(Faraway)});
_current_step = 0;
}
bool Solution::load(){
_actions.clear();
_states.clear();
std::ifstream file(_file_location);
if (!file.is_open()) { // Check if the file was successfully opened
std::cerr << "Error: Could not open the file!" << _file_location<< std::endl;
exit(-1);
}
_states.push_back((State_t){.pos=_coordinatesOfLocation(Faraway)});
Location_t currentLoc = Faraway;
bool solution_started = false;
int line_nb = 0;
std::string line;
while (std::getline(file, line)) {
line_nb++;
if (line.find("-----------------------Plan-----------------------") == 0){
solution_started = true;
continue;
}
if (!solution_started) continue;
if (line.find("Total") == 0) break;//Fin du plan
std::string err;
Action_t action = _actionFromString(line, err, line_nb);
_actions.push_back(action);
if (action.action == Move){
currentLoc = action.where;
}
_states.push_back((State_t){.pos=_coordinatesOfLocation(currentLoc)});
}
if (!solution_started){
std::cerr << "Error, no solution in file:" << _file_location;
exit(-1);
}
_current_step = 0;
_actions_strings = getActions();
return true;
}
void Solution::setCurrentStateIndex(int index){
if (index != _current_step){
_current_step = index;
}
}
Solution::ActionType_t Solution::_actionTypeFromString(std::string str, std::string &err){
if (str == "move") return ActionType_t::Move;
if (str == "pickup") return ActionType_t::Pickup;
if (str == "drop") return ActionType_t::Drop;
if (str == "chop") return ActionType_t::Chop;
if (str == "cook") return ActionType_t::Cook;
if (str == "serve") return ActionType_t::Serve;
if (str == "idle") return ActionType_t::Idle;
if (str == "yes") return ActionType_t::Yes;
if (str == "stop") return ActionType_t::Stop;
err = "Invalid action name: " + str;
//qDebug()<<err;
return ActionType_t::Stop;
}
std::string Solution::_actionTypeToString(ActionType_t act){
switch(act){
case Move: return "Move";
case Pickup: return "Pickup";
case Drop: return "Drop";
case Chop: return "Chop";
case Cook: return "Cook";
case Serve: return "Serve";
case Idle: return "Idle";
case Yes: return "Yes";
case Stop: return "Stop";
}
}
Solution::Agent_t Solution::_agentFromString(std::string str, std::string &err){
if (str == "a1") return Agent_t::A1;
err = "Invalid agent name: " + str;
//qDebug()<<err;
return Agent_t::A1;
}
Solution::Object_t Solution::_objectFromString(std::string str, std::string &err){
if (str == "onion1") return Object_t::Onion1;
if (str == "onion2") return Object_t::Onion2;
if (str == "onion3") return Object_t::Onion3;
if (str == "onion4") return Object_t::Onion4;
if (str == "onion5") return Object_t::Onion5;
if (str == "onion6") return Object_t::Onion6;
if (str == "soup") return Object_t::Soup;
if (str == "soupfromraw") return Object_t::SoupFromRaw;
if (str == "soupalreadyready") return Object_t::SoupAlreadyReady;
err = "Invalid object name: " + str;
//qDebug()<<err;
return Object_t::Onion1;
}
std::string Solution::_objectToString(Object_t object){
switch (object){
case Onion1: return "Onion1";
case Onion2: return "Onion2";
case Onion3: return "Onion3";
case Onion4: return "Onion4";
case Onion5: return "Onion5";
case Onion6: return "Onion6";
case Soup: return "Soup";
case SoupFromRaw: return "SoupFromRaw";
case SoupAlreadyReady: return "SoupAlreadyReady";
}
}
Solution::Location_t Solution::_locationFromString(std::string str, std::string &err){
if (str == "faraway") return Location_t::Faraway;
if (str == "centerloc") return Location_t::CenterLoc;
if (str == "stockloc") return Location_t::StockLoc;
if (str == "choploc") return Location_t::ChopLoc;
if (str == "cookloc") return Location_t::CookLoc;
if (str == "deliveryloc") return Location_t::DeliveryLoc;
err = "Invalid place name: " + str;
//qDebug()<<err;
return Location_t::Faraway;
}
std::string Solution::_locationToString(Location_t loc){
switch(loc){
case Faraway: return "FarAway";
case CenterLoc: return "CenterLoc";
case StockLoc: return "StockLoc";
case ChopLoc: return "ChopLoc";
case CookLoc: return "CookLoc";
case DeliveryLoc: return "DeliveryLoc";
}
}
Solution::Action_t Solution::_actionFromString(std::string str, std::string &err, int line_number){
Action_t action;
err = "";
std::replace(str.begin(), str.end(), '(', ' ');
std::replace(str.begin(), str.end(), ')', ' ');
std::vector<std::string> tokens;
// Create a string stream from the input string
std::istringstream iss(str);
std::string word;
// Extract words separated by spaces and store them in the vector
while (iss >> word) {
tokens.push_back(word);
}
if (tokens.size() < 2){
std::cerr<<"Error line "<<line_number<<": no action"<<std::endl;
exit(-1);
}
ActionType_t action_type = _actionTypeFromString(tokens[1], err);
if (err != ""){
return action;//empty action
}
switch (action_type){
case Move:
{
Agent_t agent = _agentFromString(tokens[2], err);
Location_t start = _locationFromString(tokens[3], err);
Location_t loc = _locationFromString(tokens[4], err);
return (Action_t){.action = ActionType_t::Move, .who = agent, .start = start, .where = loc};
break;
}
case Pickup:
{
Agent_t agent = _agentFromString(tokens[2], err);
Object_t object = _objectFromString(tokens[3], err);
Location_t loc = _locationFromString(tokens[4], err);
return (Action_t){.action = ActionType_t::Pickup, .who = agent, .what = object, .where = loc};
break;
}
case Drop:
{
Agent_t agent = _agentFromString(tokens[2], err);
Object_t object = _objectFromString(tokens[3], err);
Location_t loc = _locationFromString(tokens[4], err);
return (Action_t){.action = ActionType_t::Drop, .who = agent, .what = object, .where = loc};
break;
}
case Chop:
{
Agent_t agent = _agentFromString(tokens[2], err);
Object_t object = _objectFromString(tokens[3], err);
Location_t loc = _locationFromString(tokens[4], err);
return (Action_t){.action = ActionType_t::Chop, .who = agent, .what = object, .where = loc};
break;
}
case Cook:
{
Agent_t agent = _agentFromString(tokens[2], err);
Object_t object = _objectFromString(tokens[3], err);
Location_t loc = _locationFromString(tokens[7], err);
return (Action_t){.action = ActionType_t::Cook, .who = agent, .what = object, .where = loc};
break;
}
case Serve:
{
Agent_t agent = _agentFromString(tokens[2], err);
Object_t object = _objectFromString(tokens[3], err);
Location_t loc = _locationFromString(tokens[4], err);
return (Action_t){.action = ActionType_t::Serve, .who = agent, .what = object, .where = loc};
break;
}
case Idle:
{
Agent_t agent = _agentFromString(tokens[2], err);
Location_t loc = _locationFromString(tokens[3], err);
return (Action_t){.action = ActionType_t::Idle, .who = agent, .where = loc};
break;
}
case Yes:
return (Action_t){.action = ActionType_t::Yes};
break;
case Stop:
{
Agent_t agent = _agentFromString(tokens[2], err);
return (Action_t){.action = ActionType_t::Stop, .who = agent};
break;
}
}
return action;
}
std::string Solution::_actionToString(Action_t action){
std::string result(_actionTypeToString(action.action));
switch(action.action){
case Move:
result = result + ":\n" + _locationToString(action.start) + " to " + _locationToString(action.where);
break;
case Pickup:
result = result + ":\n" + _objectToString(action.what) + " at " + _locationToString(action.where);
break;
case Drop:
result = result + ":\n" + _objectToString(action.what) + " at " + _locationToString(action.where);
break;
case Chop:
result = result + ":\n" + _objectToString(action.what) + " at " + _locationToString(action.where);
break;
case Cook:
break;
case Serve:
result = result + ":\n" + _objectToString(action.what) + " at " + _locationToString(action.where);
break;
case Idle:
result = result + ":\n" + _locationToString(action.where);
break;
case Yes:
break;
case Stop:
break;
}
return result;
}
Solution::Point_t Solution::_coordinatesOfLocation(Location_t loc){
switch (loc){
case Faraway:
return (Point_t){.x=-10,.y=-10};
case CenterLoc:
return (Point_t){.x=5,.y=3};
case StockLoc:
return (Point_t){.x=10,.y=3};
case ChopLoc:
return (Point_t){.x=7,.y=6};
case CookLoc:
return (Point_t){.x=5,.y=6};
case DeliveryLoc:
return (Point_t){.x=5,.y=0};
}
}
std::vector<std::string> Solution::getActions(){
std::vector<std::string> output;
for (int i = 0 ; i<_actions.size() ; i++){
output.push_back("#"+ std::to_string(i) + " " + _actionToString(_actions[i]));
}
return output;
}
#ifndef SOLUTION_H
#define SOLUTION_H
#include <string>
#include <vector>
class Solution
{
public:
struct Point_t{
int x;
int y;
};
enum ActionType_t{
Move,
Pickup,
Drop,
Chop,
Cook,
Serve,
Idle,
Yes,
Stop,
};
enum Agent_t{
A1,
};
enum Object_t{
Onion1,
Onion2,
Onion3,
Onion4,
Onion5,
Onion6,
Soup,
SoupFromRaw,
SoupAlreadyReady,
};
enum Location_t{
Faraway,
CenterLoc,
StockLoc,
ChopLoc,
CookLoc,
DeliveryLoc,
};
enum OnionStatus_t{
RawOnion,
ChoppedOnion,
};
struct Action_t {
ActionType_t action;
Agent_t who;
Object_t what;
Location_t start;
Location_t where;
};
struct State_t {
Point_t pos;
};
bool getFileSet(){return _file_location != "";}
int getNbActions(){return _actions.size();}
std::vector<std::string> getActionsStrings(){return _actions_strings;}
int getNbStates(){return _states.size();}
int getCurrentStateIndex(){return _current_step;}
Point_t getCurrentPos(){return _states[_current_step].pos;}
std::vector<std::string> getActions();
void setCurrentStateIndex(int index);
public:
Solution(char* filename);
bool load();
private:
Point_t _coordinatesOfLocation(Location_t loc);
std::string _actionTypeToString(ActionType_t act);
std::string _agentToString(Agent_t agent);
std::string _objectToString(Object_t object);
std::string _locationToString(Location_t loc);
std::string _actionToString(Action_t action);
ActionType_t _actionTypeFromString(std::string str, std::string &err);
Agent_t _agentFromString(std::string str, std::string &err);
Object_t _objectFromString(std::string str, std::string &err);
Location_t _locationFromString(std::string str, std::string &err);
Action_t _actionFromString(std::string str, std::string &err, int line_number);
private:
std::string _file_location;
std::vector<Action_t> _actions;
std::vector<State_t> _states;
std::vector<std::string> _actions_strings;
int _current_step;
};
#endif // SOLUTION_H
File added
TP02/OvercookedVisu/assets/Courier_New18.bmp

71.4 KiB

TP02/OvercookedVisu/assets/Courier_New24.bmp

121 KiB

TP02/OvercookedVisu/assets/Pause.png

744 B

TP02/OvercookedVisu/assets/Perso.png

15.3 KiB

TP02/OvercookedVisu/assets/Play.png

870 B

TP02/OvercookedVisu/assets/Reload.png

998 B

TP02/OvercookedVisu/assets/background.png

646 KiB

#include "Solution.h"
#include "Display.h"
#include <SDL2/SDL.h>
#include <iostream>
int main(int argc, char *argv[])
{
if (argc != 2){
std::cerr<< "usage: overcooked [solutionFile]" << std::endl;
return -1;
}
Solution solution(argv[1]);
if (!solution.load()) {
std::cerr << "Failed to load solution" << std::endl;
return -1;
}
Display display(&solution);
if (!display.init("Overcooked Animation")) {
std::cerr << "Failed to initialize display" << std::endl;
return -1;
}
bool running = true;
unsigned long lastRender = 0;
while (running) {
display.handleEvents(running); // Handle events like play, pause, quit
if (clock() - lastRender > CLOCKS_PER_SEC / 60){
//unsigned long startRender = clock();
display.render(solution); // Render the current frame
//std::cerr<<"renderTime "<<(clock()-startRender)*1000./CLOCKS_PER_SEC<<"ms"<<std::endl;
} else {
SDL_Delay(5);
}
}
display.cleanup();
return 0;
}
# Overcooked Visu
## Build
### Dependecies
Overcooked needs the SDL2 and the extensions SDL2_ttf and SDL2_image development files to build.
On Ubuntu type `sudo apt install libsdl2-dev libsdl2-ttf-dev libsdl2-image-dev`
At SI, on the RedHat machines, the dependencies are already installed
### Build
Run `make` in this folder to build the software
## Run
Place your terminal in the OvercookedVisu folder and run `./overcooked <path/to/solution/file>` to launch the simulation.
If the path to your solution file has not changed, you can click on the refresh button to load a new solution and visualize it.
TP02/cookingSim.png

741 KiB | W: | H:

TP02/cookingSim.png

774 KiB | W: | H:

TP02/cookingSim.png
TP02/cookingSim.png
TP02/cookingSim.png
TP02/cookingSim.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -58,7 +58,7 @@ HTN_PATH=$(pwd)
cd $HTN_PATH
source loadEnv.bash
cd TP02/
plan cooking_domain.hddl cooking_problem.hddl debug
plan cooking_domain.hddl cooking_problem.hddl debug > plan.txt
```
## check the simulator
......@@ -66,7 +66,9 @@ plan cooking_domain.hddl cooking_problem.hddl debug
- [ ] check that the simulator is working
```
TODO - PB
cd OvercookedVisu
make
./overcooked ../plan.txt
```
## Repository Overview
......@@ -85,7 +87,8 @@ open 2 files:
```
plan cooking_domain.hddl cooking_problem.hddl debug > plan.txt
./PascalCookingSimulator plan.txt
cd OvercookedSimu
./overcooked ../plan.txt
```
- [ ] now, comment 1 line and uncomment 1 line to make the agent start "far away" from the delivery location and check that planning process will fail.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment