[Урок]Генератор карт для платформера
| |
Saitei | Дата: Понедельник, 04 Августа 2014, 19:10 | Сообщение # 1 |
старожил
Сейчас нет на сайте
| Доброго времени суток, уважаемые читатели. Сегодня я хотел бы научить вас писать генераторы карт. На самом деле данный метод несколько шаманский, ибо придумывался самостоятельно. Выражаю огромную благодарность пользователю Fade, который 2-3 года назад натолкнул на замечательные идеи на сей счёт, поделившись своими наработками. Я понятия не имею, как генерировать карты с помощью шумов Перлина. Поэтому если кто-то знает как такое сделать - пожалуйста, поделитесь опытом.
Заранее приношу извинения за свой стиль программирования, вполне возможно, что он не каждому придется по душе.
Начало начал
Первым делом надо определиться с помощью чего мы будем выводить графику. На самом деле тут особых плюшек и не требуется, можно и самостоятельно через DirectX/OpenGL загрузить и вывести на экран спрайты. Но, увы, я очень ленив, поэтому воспользуемся SFML(Simple and Fast Multimedia Library). Качаем с этого сайта.
После того, как вы скачали SFML, нам необходимо создать С++ проект. Я использую Visual Studio 2010. Запускаем IDE -> Создать проект... -> Пустой проект (Empty project) (называйте как хотите на английском, расположение так же выбирайте самостоятельно) -> OK. Далее нажимаем правой кнопкой мыши по решению "НазваниеВашегоПроекта" -> Добавить -> Создать элемент (Файл cpp, main.cpp (хотя название можно любое выбрать)). Потом: Проект -> Свойства: "НазваниеВашегоПроекта"... -> Свойства конфигурации -> C/C++ -> Общие -> (в "Конфигурация" выберите "Все конфигурации") -> Дополнительные каталоги включаемых файлов: добавьте путь к папке SFML\include. Теперь Компоновщик -> Общие -> Дополнительные каталоги библиотек: путь к папке SFML\lib. В Компоновщик -> Ввод добавьте следующие библиотеки (они все нам не нужны, но добавьте на будущее, т.к. я надеюсь, что вы продолжите писать игру : ) ): Цитата sfml-graphics.lib sfml-window.lib sfml-system.lib sfml-audio.lib Что ж, со стороны IDE справились. Осталось скинуть динамические библиотеки (dll) в папку Release и Debug. Dll файлы находятся в SFML\bin. Может быть, вы не смогли справиться с настройкой, поэтому вы можете либо посмотреть видеоурок на русском, либо прочитать это. SFML так же можно запустить под Mac OS X и Linux. За подробностями обращайтесь к урокам на официальном сайте. Там же можно узнать как использовать все фичи SFML. Однако я не советую использовать загрузку и проигрывание звуков\музыки. Это коряво реализовано для Windows XP, могут быть проблемы. Придётся самостоятельно пилить звуковой движок или качать уже готовый.
Проверка работы SFML
Вставляем в main.cpp код, который так любезно предоставил официальный сайт библиотеки: Код #include <SFML/Graphics.hpp>
int main() { sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!"); sf::CircleShape shape(100.f); shape.setFillColor(sf::Color::Green);
while (window.isOpen()) { sf::Event event; while (window.pollEvent(event)) { if (event.type == sf::Event::Closed) window.close(); }
window.clear(); window.draw(shape); window.display(); }
return 0; } Запускаем. Через некоторое время должно появиться такое окно: Если же появилась какая-то ошибка, то проверьте себя трижды или почитайте\посмотрите инструкцию по установки, которую я кидал выше (проект можно настроить для работы со статическими библиотеками, тогда нет нужды за собой таскать dll файлы). Есть вероятность, что антивирус будет ругаться. Лично у меня стоит Avast и он, похоже, очень не любит мои программы... : ))) Для того, чтобы антивирус игнорировал и не проверял проект, надо добавить исключения (гуглим, я ж лентяй : ))) ).
Пилим код! Да простит меня инквизиция! Заменяем весь код main.cpp на: Код int main() { return 0; } Этот код потом мы дополним. Создадим базовый класс Game. Для этого нажмем правой кнопкой мыши по "НазваниеВашегоПроекта" и нажмём Добавить -> Класс -> Добавить. В "Имя класса" напишите "Game". Что ж, IDE любезно сгенерировала Game.h с описанием и Game.cpp с реализацией класса. Теперь немного раздумий. Что есть класс Game? Этот класс - ядро всей игры. Он будет создавать окно игры и он будет иметь доступ к другим классам. То есть это - центральный мозг нашего чудо-юдо-генератора. Вот так выглядит мой Game.h: Код #pragma once #include <string> #include <SFML/Window.hpp> #include <SFML/Graphics.hpp> #include <math.h> #include <vector> using namespace std;
class Game { string Title; sf::RenderWindow *window; const int game_width; const int game_height; public: Game(void); //Конструктор bool Init(); //Инициализация окон и прочих систем (файл будет дополняться) bool Load(); //Загрузка ресурсов игры bool UnLoad(); //Удаление ресурсов игры из оперативной памяти void Loop(); //Главный цикл игры void Shutdown(); //Завершение работы игры ~Game(void); //Деструктор };
Game.cpp: Код #include "Game.h"
Game::Game(void): game_width(640), game_height(480) //Не пугайтесь, это всего лишь инициализация rконстант { }
bool Game::Init() { Title = "My Super Duper Omega Generator"; //Название создаваемого окна : )))))
window = new sf::RenderWindow(sf::VideoMode(game_width, game_height), Title.c_str()); if(!Load()) //Если произошла ошибка во время загрузки ресурсов игры нам необходимо незамедлительно завершить работу программы { return false; } else { //Log("Game resources load successfully"); <- Реализуйте сами : ) } return true; }
bool Game::Load() {
return true; } bool Game::UnLoad() { //Log("Game resources unloaded"); return true; }
void Game::Loop() { //Log("Running the game"); while(window->isOpen()) { sf::Event event; while(window->pollEvent(event)) { if(event.type == sf::Event::Closed) /*Если поступило событие "Закрытие окна" надо завершить работу приложения, т.е. освободить ресурсы и закрыть программу*/ { Shutdown(); window->close(); break; } } if(sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) //Если нажали ESC - выход { Shutdown(); window->close(); break; } window->clear(); window->display(); } }
void Game::Shutdown() { UnLoad(); //Log("The game shuts down\n"); }
Game::~Game(void) { }
Давайте проверим как работает то, что мы нашаманили? Измените main.cpp: Код #include "Game.h"
int main() { Game* game = new Game(); if(game->Init()) { game->Loop(); } return 0; } и запустите. Всего лишь окошко... =( Пищаль, правда? Но не отчаивайтесь, всё впереди!
Графооон! Даёшь графооон! :D
Хм... Всё круто, окно есть. Но мы же пилим генератор карт, правильно? А для этого нам нужны, по меньшей мере, спрайты. Сохраните эти спрайты в папках Release/Debug вашего проекта и назовите их land, grass и flowers соответственно:
Ого! Да у нас же будет мОйнкрУфт с травкой и цветочками!1 Создайте класс Assets (в нём мы будем хранить текстуры (для хранения музыки и другой информации - дописывайте самостоятельно))
Assets.h: Код #pragma once #include <map> #include <string> #include <SFML\Graphics.hpp> using namespace std;
class Assets { map<string,sf::Texture*>Textures; public: Assets(void); sf::Texture& Get(const string& Key); //Получить текстуру со словесным ключем void Push(const string& Key, const string& FilePath); //Положить текстуру с ключем ~Assets(void); };
Assets.cpp: Код #include "Assets.h"
Assets::Assets(void) { }
sf::Texture& Assets::Get(const string& Key) { return *Textures[Key]; }
void Assets::Push(const string& Key, const string& FilePath) { sf::Texture* some = new sf::Texture; //Создать в программной куче место под текстуру some->loadFromFile(FilePath); //Загрузить текстуру (хочу заметить, что в FilePath вместо \ надо писать \\, т.к. \ - это специальный символ С\С++ Textures[Key] = some; //Поместить указатель на текстуру с "пометкой" Key }
Assets::~Assets(void) { /*Домашнее задание: удаление всех текстур из памяти*/ }
Ну вот, класс написан.
Обновите Game.h: Цитата #pragma once #include "Assets.h" #include <string> #include <SFML/Window.hpp> #include <SFML/Graphics.hpp> #include <math.h> #include <vector> using namespace std;
class Game { string Title; sf::RenderWindow *window; Assets *res; //Здесь будем хранить ресурсы игрули const int game_width; const int game_height; public: Game(void); //Конструктор bool Init(); //Инициализация окон и прочих систем (файл будет дополняться) bool Load(); //Загрузка ресурсов игры bool UnLoad(); //Удаление ресурсов игры из оперативной памяти void Loop(); //Главный цикл игры void Shutdown(); //Завершение работы игры ~Game(void); //Деструктор };
И Game.cpp: Цитата #include "Game.h"
Game::Game(void): game_width(640), game_height(480) //Не пугайтесь, это всего лишь инициализация переменных {
}
bool Game::Init() { Title = "My Super Duper Omega Generator"; //Название создаваемого окна : )))))
window = new sf::RenderWindow(sf::VideoMode(game_width, game_height), Title.c_str()); if(!Load()) //Если произошла ошибка во время загрузки ресурсов игры нам необходимо незамедлительно завершить работу программы { return false; } else { //Log("Game resources load successfully"); <- Реализуйте сами : ) } return true; }
bool Game::Load() { res = new Assets(); return true; } bool Game::UnLoad() { delete res; //Log("Game resources unloaded"); return true; }
void Game::Loop() { //Log("Running the game"); while(window->isOpen()) { sf::Event event; while(window->pollEvent(event)) { if(event.type == sf::Event::Closed) /*Если поступило событие "Закрытие окна" надо завершить работу приложения, т.е. освободить ресурсы и закрыть программу*/ { Shutdown(); window->close(); break; } } if(sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) //Если нажали ESC - выход { Shutdown(); window->close(); break; } window->clear(); window->display(); } }
void Game::Shutdown() { UnLoad(); //Log("The game shuts down\n"); }
Game::~Game(void) { } Теперь давайте напишем класс GameMap? Этот класс будет содержать информацию о расположении блоков.
GameMap.h: Код #pragma once #include <vector> #include "Assets.h" using namespace std;
struct Block { int x,y; int block_type; };
class GameMap { public: vector<Block*>blocks; GameMap(); ~GameMap(void); };
GameMap.cpp: Код #include "GameMap.h"
GameMap::GameMap() {
}
GameMap::~GameMap(void) { for(int i = 0; i < blocks.size(); i++) { delete blocks[i]; } }
Всё вроде как хорошо, но что такое block_type? Это тип блока. Допустим, числу 0 соответствует блок земли, 1 - блоку травы и т.д. Но согласитесь - помнить номера блоков не очень удобно. Для этого создадим block_types.h: Код #pragma once
enum { LAND, GRASS, FLOWERS, };
Надобно обновить класс Game:
Game.h: Код #pragma once #include "Assets.h" #include "block_types.h" #include "GameMap.h" #include <string> #include <SFML/Window.hpp> #include <SFML/Graphics.hpp> #include <math.h> #include <vector> using namespace std;
class Game { string Title; sf::RenderWindow *window; Assets *res; //Здесь будем хранить ресурсы игрули GameMap *map; const int game_width; const int game_height; public: Game(void); //Конструктор bool Init(); //Инициализация окон и прочих систем (файл будет дополняться) bool Load(); //Загрузка ресурсов игры bool UnLoad(); //Удаление ресурсов игры из оперативной памяти void Loop(); //Главный цикл игры void Shutdown(); //Завершение работы игры ~Game(void); //Деструктор };
Game.cpp: Код #include "Game.h"
Game::Game(void): game_width(640), game_height(480) //Не пугайтесь, это всего лишь инициализация переменных { }
bool Game::Init() { Title = "My Super Duper Omega Generator"; //Название создаваемого окна : )))))
window = new sf::RenderWindow(sf::VideoMode(game_width, game_height), Title.c_str()); if(!Load()) //Если произошла ошибка во время загрузки ресурсов игры нам необходимо незамедлительно завершить работу программы { return false; } else { //Log("Game resources load successfully"); <- Реализуйте сами : ) } return true; }
bool Game::Load() { res = new Assets(); res->Push("LAND","land.png"); res->Push("GRASS","grass.png"); res->Push("FLOWERS","flowers.png");
map = new GameMap(); return true; } bool Game::UnLoad() { delete res; delete map; //Log("Game resources unloaded"); return true; }
void Game::Loop() { //Log("Running the game"); while(window->isOpen()) { sf::Event event; while(window->pollEvent(event)) { if(event.type == sf::Event::Closed) /*Если поступило событие "Закрытие окна" надо завершить работу приложения, т.е. освободить ресурсы и закрыть программу*/ { Shutdown(); window->close(); break; } } if(sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) //Если нажали ESC - выход { Shutdown(); window->close(); break; } sf::Sprite some; for(int i = 0; i < map->blocks.size(); i++) //Рисуем карту { switch(map->blocks[i]->block_type) { case LAND: { some.setTexture(res->Get("LAND")); break; } case GRASS: { some.setTexture(res->Get("GRASS")); break; } case FLOWERS: { some.setTexture(res->Get("FLOWERS")); break; } } some.setPosition(map->blocks[i]->x, map->blocks[i]->y); window->draw(some); } window->clear(); window->display(); } }
void Game::Shutdown() { UnLoad(); //Log("The game shuts down\n"); }
Game::~Game(void) { }
Я специально не помечал измененные места, ищите сами (:
Пишем генератор карт Подошли к последнему и самому главному пункту - генерации карты. Попробуйте придумать самостоятельно генератор карт, возможно, у вас получится. Если же не получилось - читайте про тот способ, что использую я. Итак. У нас есть блоки размером 32 на 32 пикселя. Будем считать, что один такой блок помещается в одну ячейку карты. Имеем карту map_width на map_height (т.е. у нас map_width*map_height ячеек (вспомните формулу нахождения площади прямоугольника: S = a*b)). Для того, чтобы "сгенерировать" карту всего лишь нужно псевдослучайным способом сгенерировать кривую на определенных высотах. Потом всё, что ниже этой кривой, заполнить блоками и сверху поставить цветочки. Оптимизации ради я буду сразу же генерировать столбцы карты. Т.к. у нас уже есть класс GameMap, то мы будем отдавать объект этого класса генератору, чтобы он наполнял его информацией об иной карте.
Создайте класс MapGenerator.
MapGenerator.h: Код #pragma once #include "block_types.h" #include "GameMap.h" #include <time.h>
class MapGenerator { int h_min; //нижняя граница int h_max; //верхняя граница public: MapGenerator(void); void Generate(vector<Block*>&blocks, const int map_width, const int map_height); ~MapGenerator(void); };
MapGenerator.cpp: Код #include "MapGenerator.h" #include <iostream>
MapGenerator::MapGenerator(void) { }
int Random(int a, int b) { int result = a + rand()%(b-a+1); return result; }
void MapGenerator::Generate(vector<Block*>&blocks, const int map_width, const int map_height) { /*Удаляем старую карту*/ for(int i = 0; i < blocks.size(); i++) { delete blocks[i]; } blocks.clear(); h_min = 1 + Random(4,5); h_max = map_height - 1 - Random(2,3); int height = Random(h_min, h_max); for(int x = 0; x < map_width; x++) { blocks.push_back(new Block()); blocks[blocks.size() - 1]->block_type = GRASS; blocks[blocks.size() - 1]->x = x; blocks[blocks.size() - 1]->y = height; if(Random(-3,3) == 0) { blocks.push_back(new Block()); blocks[blocks.size() - 1]->block_type = FLOWERS; blocks[blocks.size() - 1]->x = x; blocks[blocks.size() - 1]->y = height - 1; }
for(int y = height+1; y < map_height; y++) { std::cout<<Random(-1,1)<<endl; blocks.push_back(new Block()); blocks[blocks.size() - 1]->block_type = LAND; blocks[blocks.size() - 1]->x = x; blocks[blocks.size() - 1]->y = y; }
height += Random(-1,1); if(height > h_max) { height -= 2; } else if(height < h_min) { height += 2; } } }
MapGenerator::~MapGenerator(void) { }
Меняем Game.cpp:
Код #include "Game.h"
Game::Game(void): game_width(640), game_height(480) //Не пугайтесь, это всего лишь инициализация переменных { }
bool Game::Init() { Title = "My Super Duper Omega Generator"; //Название создаваемого окна : )))))
window = new sf::RenderWindow(sf::VideoMode(game_width, game_height), Title.c_str()); if(!Load()) //Если произошла ошибка во время загрузки ресурсов игры нам необходимо незамедлительно завершить работу программы { return false; } else { //Log("Game resources load successfully"); <- Реализуйте сами : ) } return true; }
bool Game::Load() { res = new Assets(); res->Push("LAND","land.png"); res->Push("GRASS","grass.png"); res->Push("FLOWERS","_flowers.png");
map = new GameMap(); mapGen.Generate(map->blocks, (int)(game_width/32), (int)(game_height/32)); return true; } bool Game::UnLoad() { delete map; delete res; //Log("Game resources unloaded"); return true; }
void Game::Loop() { //Log("Running the game"); while(window->isOpen()) { sf::Event event; while(window->pollEvent(event)) { if(event.type == sf::Event::Closed) /*Если поступило событие "Закрытие окна" надо завершить работу приложения, т.е. освободить ресурсы и закрыть программу*/ { Shutdown(); window->close(); break; } } if(sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) //Если нажали ESC - выход { Shutdown(); window->close(); break; } if(sf::Keyboard::isKeyPressed(sf::Keyboard::R)) { mapGen.Generate(map->blocks, (int)(game_width/32), (int)(game_height/32)); }
sf::Sprite some; window->clear(); for(int i = 0; i < map->blocks.size(); i++) //Рисуем карту { switch(map->blocks[i]->block_type) { case LAND: { some.setTexture(res->Get("LAND")); break; } case GRASS: { some.setTexture(res->Get("GRASS")); break; } case FLOWERS: { some.setTexture(res->Get("FLOWERS")); break; } } some.setPosition(map->blocks[i]->x*32, map->blocks[i]->y*32); window->draw(some); } window->display(); } }
void Game::Shutdown() { UnLoad(); //Log("The game shuts down\n"); }
Game::~Game(void) { } и Game.h: Код #pragma once #include "Assets.h" #include "block_types.h" #include "GameMap.h" #include "MapGenerator.h" #include <string> #include <math.h> #include <vector> using namespace std;
class Game { string Title; sf::RenderWindow *window; Assets *res; //Здесь будем хранить ресурсы игрули GameMap *map; MapGenerator mapGen; const int game_width; const int game_height; public: Game(void); //Конструктор bool Init(); //Инициализация окон и прочих систем (файл будет дополняться) bool Load(); //Загрузка ресурсов игры bool UnLoad(); //Удаление ресурсов игры из оперативной памяти void Loop(); //Главный цикл игры void Shutdown(); //Завершение работы игры ~Game(void); //Деструктор };
ВНИМАНИЕ! Если вы подключали SFML точно так же, как и я, то для тестирования проекта используйте Release. В Debug будут ошибки (это связано с тем, что библиотеки подключены для релиза)
Сообщение отредактировал Saitei - Понедельник, 18 Августа 2014, 20:52 |
|
| |
Notin | Дата: Понедельник, 04 Августа 2014, 19:36 | Сообщение # 2 |
заслуженный участник
Сейчас нет на сайте
| Хоть сам и не пишу на С++, но думаю что урок будет очень полезен, кстати, почему не урок по написанию змейки!
Twitter ВКонтакте
|
|
| |
Saitei | Дата: Понедельник, 04 Августа 2014, 19:50 | Сообщение # 3 |
старожил
Сейчас нет на сайте
| Цитата Notin ( ) Хоть сам и не пишу на С++, но думаю что урок будет очень полезен, кстати, почему не урок по написанию змейки! cool Запросов не было) А надо? Я могу. Главное графику найти (чтобы змейка не такой унылой получилась)
|
|
| |
Notin | Дата: Понедельник, 04 Августа 2014, 19:56 | Сообщение # 4 |
заслуженный участник
Сейчас нет на сайте
| Saitei, да это ж шутка, тыж любишь змейки писать
Twitter ВКонтакте
|
|
| |
Saitei | Дата: Понедельник, 04 Августа 2014, 21:47 | Сообщение # 5 |
старожил
Сейчас нет на сайте
| Notin, не, просто на ассемблере надо было написать. В то время я даже не знал как её на С написать. Голову 2 часика ломал и в итоге написал прототип на С. Потом быстренько написал на ассемблере. Кроме того я ещё Х-О писал! :С
|
|
| |
МаоДзедун | Дата: Понедельник, 04 Августа 2014, 22:16 | Сообщение # 6 |
почетный гость
Сейчас нет на сайте
| Выложи на главной в статьи !!! Статьи реально хорошая
Знакомая попросила переустановить Windows, взял дистрибутив Ubuntu Интеллигенция — самая необразованная часть общества.©Мао Дзэдун Кто не побывал на Великой китайской стене, тот не может считаться китайцем.©Мао Дзэдун
|
|
| |
Saitei | Дата: Вторник, 05 Августа 2014, 15:50 | Сообщение # 7 |
старожил
Сейчас нет на сайте
| МаоДзедун, по вашей просьбе так и сделаю
Сообщение отредактировал Saitei - Вторник, 05 Августа 2014, 15:50 |
|
| |
romgerman | Дата: Вторник, 05 Августа 2014, 20:54 | Сообщение # 8 |
старожил
Сейчас нет на сайте
| Зачем выкладывать на форуме, если есть раздел статей?
|
|
| |
МаоДзедун | Дата: Вторник, 05 Августа 2014, 21:41 | Сообщение # 9 |
почетный гость
Сейчас нет на сайте
| Аффтар жжот нипадецки
Знакомая попросила переустановить Windows, взял дистрибутив Ubuntu Интеллигенция — самая необразованная часть общества.©Мао Дзэдун Кто не побывал на Великой китайской стене, тот не может считаться китайцем.©Мао Дзэдун
|
|
| |
Saitei | Дата: Суббота, 09 Августа 2014, 11:39 | Сообщение # 10 |
старожил
Сейчас нет на сайте
| По уроку у всех всё получилось? Кстати... Если кто-нибудь будет использовать много текстур, то std::map надо заменить хотя бы на std::vector. Мм... К слову, ещё какие-нибудь уроки нужны?
|
|
| |
vasua99 | Дата: Суббота, 09 Августа 2014, 21:54 | Сообщение # 11 |
GNU follower
Сейчас нет на сайте
| а лучше вообще грузить все спрайты в один большой буфер, и сохранять смещения спрайтов) Добавлено (09.08.2014, 21:54) ---------------------------------------------
Жизнь игра, и мы в ней пешки... А я кушаю пельмешки)
|
|
| |
Saitei | Дата: Суббота, 09 Августа 2014, 22:54 | Сообщение # 12 |
старожил
Сейчас нет на сайте
| Цитата vasua99 ( ) а лучше вообще грузить все спрайты в один большой буфер, и сохранять смещения спрайтов) Например?
|
|
| |
vasua99 | Дата: Суббота, 09 Августа 2014, 23:46 | Сообщение # 13 |
GNU follower
Сейчас нет на сайте
| Что то типо такого Код typedef struct Sprite { size_t offset; int size_x; int size_y; // etc } Sprite;
std::list<Sprite *> LoadSprites(uint8_t *buf, size_t bufSize, char filenames[], int count) { size_t currOffset = 0; size_t readed; int size_x; int size_y; std::list<Sprite *> sprites; for (int i = 0; i < count; i++) { FILE *sprite_file = fopen(filenames[i], "r"); // for example - sprite is a file with sizes // in first line and "raw rgb colors" at others if (fscanf(sprite_file, "%d %d\n", &size_x, &size_y) == 2 && size_x > 0 && size_y > 0) { if (currOffset + size_x * size_y >= bufSize) { fprintf(stderr, "ERROR: Failed load sprites - not enough memory\n"); return sprites; } readed = 0; for (int j = 0; j < size_x * size_y; j++, currOffset++, readed++) { int ch = fgetc(sprite_file); if (ch != EOF) buf[currOffset] = getchar(); else break; } if (readed == size_x * size_y) { Sprite *sprite = { currOffset, size_x, size_y }; sprites.push_back(sprite); continue; } else { currOffset -= readed; } } fprintf(stderr, "ERORR: Failed load sprite \"%s\"\n", filenames[i]); } return sprites; }
Жизнь игра, и мы в ней пешки... А я кушаю пельмешки)
|
|
| |
-l33t-h4xx- | Дата: Понедельник, 11 Августа 2014, 10:10 | Сообщение # 14 |
участник
Сейчас нет на сайте
| Цитата vasua99 ( ) std::list<Sprite *> LoadSprites(uint8_t *buf, size_t bufSize, char filenames[], int count) Такой типичный сишный код: "Я не хочу выделять память, сделай это за меня."
Как правильно задавать вопросы
Сообщение отредактировал -l33t-h4xx- - Понедельник, 11 Августа 2014, 10:12 |
|
| |
Saitei | Дата: Понедельник, 11 Августа 2014, 14:23 | Сообщение # 15 |
старожил
Сейчас нет на сайте
| Цитата -l33t-h4xx- ( ) сишный код Тоже заметил это. Но не считаю, что это плохо. Единственное - если человек пишет на С, то он должен писать именно на С, без С++. Если на С++ - то пусть пишет на С++. Си в некоторых местах выигрывает по сравнению с си++, имхо
|
|
| |
vasua99 | Дата: Понедельник, 11 Августа 2014, 17:25 | Сообщение # 16 |
GNU follower
Сейчас нет на сайте
| Ну скажем так из С++ тут только совсем капля STLa. Ну а про выделение памяти - писалось в 2 часа ночи, в полусонном бреду, спать хотелось.. по хорошему надо юзать библиотеку со структурами данных или написать самому)
Жизнь игра, и мы в ней пешки... А я кушаю пельмешки)
|
|
| |
PolarBear | Дата: Понедельник, 18 Августа 2014, 20:30 | Сообщение # 17 |
был не раз
Сейчас нет на сайте
| Цитата Saitei ( ) По уроку у всех всё получилось? Увы, компилятор жалуется:
>"1>Game.cpp(33): error C2065: mapGen: необъявленный идентификатор" ну и соответственно: >1>Game.cpp(33): error C2228: выражение слева от ".Generate" должно представлять класс, структуру или объединение в строке: >mapGen.Generate(map->blocks, (int)(game_width/32), (int)(game_height/32));
Объявлять, чтобы быть уверенным, что я ничего не сломаю (ибо я бом бом в крестах, как и во всём другом, лол) окромя переменных я ничего не умею. Прошу автора подсказать, где и как сиё объявить.
|
|
| |
Saitei | Дата: Понедельник, 18 Августа 2014, 20:53 | Сообщение # 18 |
старожил
Сейчас нет на сайте
| Цитата PolarBear ( ) >"1>Game.cpp(33): error C2065: PolarBear, pmapGen: необъявленный идентификатор" ну и соответственно: Забыл последний апдейт Game.h выложить. Просто после "private:" допиши "MapGenerator mapGen;".
|
|
| |
PolarBear | Дата: Понедельник, 18 Августа 2014, 20:58 | Сообщение # 19 |
был не раз
Сейчас нет на сайте
| Цитата Saitei ( ) после private А ведь его то тоже нет.
P.S. Всё, вижу.
Сообщение отредактировал PolarBear - Понедельник, 18 Августа 2014, 21:00 |
|
| |
Saitei | Дата: Понедельник, 18 Августа 2014, 21:00 | Сообщение # 20 |
старожил
Сейчас нет на сайте
| Цитата PolarBear ( ) А ведь его то тоже нет. Значит перед "public:". Там private неявно находится.
|
|
| |
|