开发者

MVC Game Design with objects

I wrote a simple sokoban like 2D game in python that I want to clean up. It's done in a sort-of OO way where each object in the game ha开发者_运维百科s a Draw function I can call to redraw the screen. It works out nicely since I can loop through each position on the screen and call the object's draw function.

I am learning about design patterns, and I really like the benefits of MVC, but I don't see a clean way to separate the draw function each object has from the model to put into the view. Is there a good way to do this? Is this a case where I should not use a MVC design?


MVC can be counter-intuitive sometimes, especially when you're first learning OO and discover that having a "draw" method makes things so organized!

Here's an overview of one of many ways you might implement MVC for your game:

Model:

  • "Box": box_type, pos_x, pos_y
  • "BoxManager": list(Box)
  • "GameState": box_manager, player_manager, goal_manager, ...
  • "Move": dx, dy

Controller:

  • "GameController": check_valid_move(move), move_player(move), is_goal_state(), ...

View:

  • "Screen": render()
  • "PlayerRenderer": render()
  • "BoxRenderer": render_box(box), render_all_boxes()

Notice how the model is totally self-contained and does not reference the controller or view modules. This is one of the key aspects of MVC. The controller takes player input and manipulates the global game state. And the view looks at the global game state and renders the screen.

You don't have to go this route, but it's an option worth understanding and considering.


Refactoring your code to conform to MVC would mean creating a "view" (like that represented your screen, and that view would have (for example) a draw method that took the "model" (a python object that contained all of the block states) and rendered that model to the screen.

Now perhaps all that draw method would do to render to the screen is call a renderToScreen(screenView) method on every block object. Or you might refactor that draw method into the view if you want to be more "pure".


One aspect that I'll just quickly make explicit is that when your model changes, it can't call the view to say "render this change" - because the model shouldn't know about the view(s).

Instead the model raises an event to say it has changed, and the view re-renders as necessary on receiving these. The view(s) know about the model, and subscribes to its events, but the model knows nothing about the things receiving the events.

As an example, I'm writing an OpenGL app, where the model contains simple normalized polygons and polyhedra, which are nice to work with geometrically, but are not convenient to pass to OpenGL. When the view receives an event saying the model has changed (a shape added or modified) then the view converts these polygons into the denormalised arrays of vertices that can be passed to OpenGL. This is an expensive operation, so the view caches these arrays in its own collection of "what needs to be rendered", and when it renders, it just iterates through this 'view collection', passing each array to OpenGL. So the view is the only code that knows about OpenGL, and is the only code that knows how to convert model state into OpenGL structures.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜