I am making a game in java using the MVC design pattern (with swing) and I do not know how to make the Controller class separate from the view Class.
until now I have a model that contains all the data, a controller which in charge of all the logic and now I think about how to separate the view.
I have the GameView which extends the Jpanel and has a paintComonent:
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
draw(g2D);
}
public void draw(Graphics2D g2D){
drawComponent(background, g2D);
drawComponent(arenaController.getArena().getPlane(), g2D);
drawComponent(arenaController.getArena().getPlayer().getBoat(), g2D);
ArrayList<PlaneDrop> planeDrops = arenaController.getArena().getPlaneDrops();
for(PlaneDrop planeDrop : planeDrops){
drawComponent(planeDrop, g2D);
}
g2D.drawString("Life: " + arenaController.getArena().getPlayer().getLife(), 10, 30);
g2D.drawString("Score: " + arenaController.getArena().getPlayer().getScore(), GAME_WIDTH - 50, 30);
}
but on the other hand, I have the GameEngine which in charge of the configuration and run
#Override
public void run() {
arenaController.init();
long waitTime = 0;
Graphics g = this.getGraphics();
gameViewer.paintComponent(g);
while(arenaController.isRunning()){
long startTime = System.currentTimeMillis();
gameViewer.paintComponent(g);
update(); // update game
gameViewer.repaint();
long endTime = System.currentTimeMillis() - startTime;
waitTime = (MILLISECOND / FPS) - endTime / MILLISECOND;
try{
Thread.sleep(waitTime);
} catch (Exception e){}
}
}
the run() method in the engine invokes the paintComponent() method of the view (which for me sounds like the controller --> invokes the viewer) but I find it is not the best way to do that and it is not recommended to invoke the paintComponent() directly.
So I want a clear separation of the controller and the view but I having trouble finding the appropriate way to do that.
Okay, so you're running into a series of problems.
First
Swing is already a MVC
Second
The form of "MVC" which is taught and discussed today isn't actually how the original intent of MVC was meant to be used. It was considered more of guide line or recommendation than a stead fast rule or paradigm.
The problem is, you end up with "purests" who insist on an absolute separation of all models, controllers and views, in some cases, to the detriment of the API or solution (this when you end up with "massive view controller" problems).
Why? Consider a button. It's a view, it has a model and it can act as a controller.
You don't need a seperate "controller" to control the button. It can register the keyboard and mouse actions it needs to monitor with the underlying system. It can coordinate changes between the model and itself (the view) and it becomes a self contained unit of work.
Seriously, could you imagine having to create a seperate controller every time you created a button or any other UI component ... 😱😓
When you add the button to another container (view), the button is acting as it's own view/controller. The parent container may then have a larger model and a number of sub views which it is "controlling" or coordinating.
The container may also be controlled via an external controller which is acting to coordinate the changes between the container and the large model, allowing it to be decoupled, but in this case, I would design it in such away so that the implementation logic was decoupled, so that the outter controller didn't care about "how" stuff got done, just that there was a contract in place to allow of the passage of information between these layers.
So, what's the point?
Don't get hung up on trying to produce a "clean" MVC, especially in Swing, you're going to be tearing your hear out.
Also remember, you can have a controller talk to another controller, this allows it to disseminate information where sub controllers don't need or want all the information which might be available to the parent controller. It also allows it to control distinctly different controllers, allowing for a greater decoupling of elements and a nice plug and play approach.
So, how does this help you?
This should provide you with some places to jump off from.
If you don't want the GameEngine to talk directly to the view, you could establish a "rendering" controller. Who's responsibility would be to coordinate changes made by the game engine to the model with the underlying view (ie, schedule a rendering pass).
This would allow the GameEngine to "control" one or more "rendering" controllers and allow for a separation in how the underlying rendering is actual done from the GameEngine
You can do this because a controller can be responsible for other controllers - it's just a coordinator between the model and the next layer (typically a view)
In this example, you could change the rendering system simply by changing the implementation of the "rendering" controller (and if you're using interfaces, this becomes much simpler) without effecting the GameEngie, which, at the end of the day is the benefit of following this type of design - separation of responsibility through de-coupling.
Passing thoughts...
Don't, ever, call paintComponent directly. There is a reason why it's protected
Don't use getGraphics. This isn't how custom painting is done in Swing. getGraphics is at best just a snapshot of the last paint pass made by Swing. Remember, in Swing, you don't control the painting process, this is taken care of for you, instead, you schedule a paint pass (ie repaint) and let the system take care of the reset
If you want/need control over the painting process, then you need to use a java.awt.Canvas and a BufferStrategy instead.
Solution:
A good way to split data and logic in a Game is using an Entity Component System.
LibGDX's Ashley is what I use.
These Systems help keeping even the largest games relatively clean and understandable.
However there is some initial work required, so for small games you might just be better off with mixing logic and data in classes like Player or Enemy, put all instances of your Game Objects into a List and have a Canvas that paints them all ordered by their Z-Index.
Brief explanation of an Entity Component System:
In an Entity Component System you Entities as your Game Objects. These Entites are like empty objects, but with the capability to take posess an indefinite amout of Components (one per Component Type). These Components give the Entity the ability to be something (like extending an Class, but not limited to one).
So if your Entity has a TextureComponent it is displayable, but without giving it a TransformComponent it cannot yet be drawn at a specific location. If you now also give it a BodyComponent it can have a physical body in your world and can be pushed around. The TransformComponent will be updated everytime the Body is moved.
All the Logic is performed by Systems. The process all Entites with specific Component Types.
A self drawn visualization (I apologize for the looks, I'm not an artist):
Related
I'm writing simple solar system simulator.
This is my first libgdx project. I'm using a Stage and Actors for the main menu and is pretty handy especially touch events handling. But ... looking at the examples i see nobody uses actors in actual game logic. I wander if i should use actor as a parent of planet class or just write my own class tor that.
The planets won't be touchable and they will be moved only between the frames so the third parameter of action MoveBy will have to be time between frames.
That are the cons. What are the pros for using Actors?
The main pros for Actors are Actions, Hit testing and touch events, and Groups of Actors.
Actions make quick and easy tweening if your game logic needs that.
You can call stage.hit(x, y) at any time to return the first actor that returns true to whatever hit logic you wrote for it (usually checking bounds with x, y, width, height). return this actor or null to keep iterating through the actors' hit methods looking for a hit actor. Null is returned if no actor is hit.
Hit is used for the Stage's touch events. The actor's touch methods are passed local coordinates, and the Stage handles overlapping of objects, e.g. if an actor covers another actor such that the other actor shouldn't receive touchDown, return true on the covering actor to stop the calling of touchDown on actors "beneath". This also sets 'focus' on the actor that returns true so that Actor's touchUp will be called.
You can group actors together to perform Actions, touch events, etc on the entire Group of Actors as a single unit.
Some Cons:
Actors require a stage which limits functionality somewhat. Many coders use other logic to determine game object state, rather than the scene2d Actions (e.g. box2d). If you use Actors for game objects, you will probably want two Stages, one for ui and one for game world. If you don't use them you'll probably be using your own SpriteBatch and Camera anyway though. And keep in mind that Actors only have an abstract Draw method so you will still need to create draw logic anyway. You'll probably keep a TextureRegion or Sprite as a private field for the Actor. If you want to use your own update logic, you can override the act(float delta) method to get the delta time (call super.act(delta) if you use Actions).
So if you have your own logic and won't use much of what Stage has to offer, save some resources and roll your own application-specific solution. If you can use some of the pros without limiting needed functionality then go for a second Stage for the game logic.
I'm working on a small Chess game and think I'm almost done with the basic model and ready to start writing the GUI.
What I've been wondering for a long time is that if the Chess board is represented by a Square array of [8][8], and I create a method to draw a square and somehow establish a relation between that method and the Square model, will I then magically have a visual Chess board?
I mean, say that a square is 10x10 pix, does that mean that the first element (represented by a square) will begin at (0, 0), element two at (10, 0), element/square nine at (0, 10) etc?
When I checked out Graphics2D I noticed that the method to draw a rectangle requires x and y coordinates, what do I do if I want the position to depend on the array element?
Or I am going to have to write down the coordinates of each square on the board?
Another thing that has been bothering me is whether it's [row][column] or [column][row]?
I've been using [column][row] in my code since it seems right if you think of it as (x, y).
When you move up and down you change the row, = y, etc.
I've been trying to google around to find out how to apply the MVC-design, what to think about, do's an dont's, etc. The only thing I know this far is that model = data logic, view = gui and control = interaction, the conclusion is that either I'm bad at googling or there isn't any good information targeted at beginners regarding MVC.
Mainly I don't really understand the relation between M, V and C.
So, let's get the easy question out of the way: as far as 2D arrays goes, it's actually up to you to decide whether it's [row][column] or [column][row]. Java doesn't care. As long as you treat it consistently throughout your app you can think of it whichever way makes most sense to you. If it helps (and it might not) remember that a 2D array is just an array of arrays.
As for MVC, this is how I think of it: M is the model of the data (the array, for example), V is the visual representation of that data (displayed to the user, as a chessboard perhaps) and C is the controller, which connects the two and transmits changes in one to the other, translating or otherwise interpreting user actions as necessary. If the user drags a chess piece from one square to another, the Controller interprets this gesture, implements the logic that decides if the maneuver is legal and what side-effects it might have (like capturing a piece), and updates both the model and the view as required. The confusion lies in that most UI toolkits, Java's included, often blur the boundaries between these pieces, so that bits of the Controller end up in the View, or the Model, or both. It's not necessarily a problem, but it's something to be aware of. The main thing is to try, as far as possible, to keep a well-defined boundary between the data, the view, and the logic that interfaces the two.
To answer your question about drawing and co-ordinates, it really depends how you implement your chessboard UI. You could implement it entirely using Java Swing, for example, and by making clever use of JLabels, JPanels, and maybe a GridLayout, or perhaps even a JTable, you could almost (almost!) have an automagially updating chessboard. On the other hand, you could implement your own UI classes from scratch, making use of Java2D and the drawing primitives it provides, and then you'd have to do more management of co-ordinates and such.
Ri8 dear... Actually .. we cant seen clearly advantages of MVC architecture in small application means window based small application... but when you r going with large scale enterprise application .. you realize that ..
When large enterprise level distributed system developing there are lots of developers, designers and other persons are working with it. Now , suppose developer make designing in their coding part .. so it is very hard to understand by any designer.. so this part is seperated so disigner can easily modified and udnerstand this very well and for that there is no need of help of programmer and its a VIEW component....
Same as if there is some business logic is combined with view components then it is hard to understand by programmer and it take too much time to separate that logic from VIEW component, so any programmer can easily & speedly understand that logic .. so Logic means Model and design means any GUI part means VIEW component is separated...
Now Controller .. component .. so, CONTROLLER component provide bridge between those two model and view component.. menan it decided that which view may be given to end user..
and it controll View with the help of model component.............
GOt .. IT........!!!!...
IF any Suggestion... Most Well Come...................
EDIT: i just deleted the entire post and reformulated the question to be more generic.
I want to do a simple strategy game: map, units.
Map: one class. Units: another class, self drawn.
Simple questions:
How does an unit should redraw itself on the map.
A unit should be a JPanel or similar Swing component (just to be able to manage them as an entity with its own mousehandlers) or can be another thing, without neglecting the fact that it should be an autonomous object with its own action handlers and fields.
Is this map-units model correct of a simple game that would help me to learn in a fun way Java and OOP fundamentals.
Thats it!
There are 2 ways.
Either have a Map class which is the main JPanel, to maintain the collection of units, but keep the Unit class as non-Swing. When the Map's paint() method is called, ask each Unit to redraw itself by calling a method in each visible Unit. The Unit could be inherited from any base class, for example Rectangle, or some other data structure you use in the program. In this case, the Unit class handles painting and calculations, but the Map handles the clicks and events for each Unit. It could pass the message on to the Unit if needed; however, if the unit itself doesn't need to know about these things, this method works well. The Unit class is light and economical. You can also decide whether the Unit knows its position in the Map or not.
Or have each unit as a JComponent, and handle its own events separately. The disadvantage is that each instance of a Unit creates a pile of data for drawing it as well. So if you have hundreds of units, only a couple of which are drawn, this way is not efficient. The advantage is each unit can handle its own GUI events without translation etc. This assumes also a 1:1 mapping of actual units in the game and graphical units on the screen. Also it is trickier to implement certain event handlers in the Unit, if a Unit needs to know about what other Units are around!
A third and arguably better way is to have a purely data Unit class, containing the game information about the unit, as in (1), but which has a method to create the JComponent when needed. The JComponent could, for example, be an inner class in the Unit - it could then access the Unit data. This is great if a unit may need to be displayed in 2 places (e.g. on 2 screens or views).
--
Addendum to address comments
That is correct, in (1) the Map (main JPanel) implements the mouse handler, and asks each unit in turn if it is 'hit'. This allows you to do more complex things, such as have 2 units overlapping/on top of each other, and both could respond to the click.
Also, for example, they may not be rectangular, or may be drawn with an alpha channel (if the Units were JComponents, they will by default grab any mouse event over their whole rectangle, to themselves). If your units don't overlap and are in their own rectangles, then JComponent's own mouse handler is enough.
If you use approach (1), the Map can ask each unit whether it contains a clicked point, and the Map can then handle the 'selection' process. Remember, a unit on its own won't be able to work out what other units are selected - selection may involve deselecting another unit. In that case, the selection operation is really a Map operation, not a Unit operation, although it may change the appearance or function of the Unit as well.
If you use separate JComponents for the Units, you can override contains(Point) to determine if the mouse hits the item, but this won't let other Units also respond to the click. But each Unit could 'select itself' (set a flag used when drawing) then notify the Map (it will need to find it using getParent or by a preset property).
Key things you need to know before deciding on this design would be:
Will you ever need more than one 'Map' panel per game?
Will you ever need more Unit objects than are to be displayed?
Will you ever need to display a Unit more than once?
If the answers are yes, you should separate the 'Data' classes from the 'View' classes, as suggested in 3.
then: What does a Unit need to 'do' and what does it need to know about the Map and other Units in order to do this? e.g. moving is usually done by the Map class in this situation, as it depends on the Map and on other Units; drawing is best done by the Unit because there may be many unit subtypes with different data structures that may need to be drawn; Unit selection operations as you have pointed out lie somewhere in between. If you see how Swing implements this (e.g. ButtonGroup, ListSelectionModel), the 'selection' itself can be though of as a separate class.
I made a peg solitaire game a few years ago which was pretty much just a JPanel that extended MouseListener and MouseMotionListener. The pegs were primitive circles drawn in the paint method, but you could track where they landed by taking the cursor position and mathematically working out the square in which it landed. That lined up with an array that stored either a 1 or 0 for each square on the board depending if anything was there. You could also drag each piece by finding the current cursor position then calling repaint() in the mouseDragged method you get from implementing MouseMotionListener.
I'd probably suggest doing it that way to begin with. Create an array of whatever size and use that to track the units. Then each time you make a move just check that array and redraw your units in the paint method. If you're using mouse movement then you can get the current position of the unit on mouseDown then do what I mentioned before with mouseDragged, and then get your final location on mouseUp and also do your calculations in regards to legal moves etc in mouseUp.
In the paint method you'll just loop over the array that defines the map and if there is a unit at the current position on the array then do something like g.fillOval(x,y,x_dimension,y_dimension). That array could just have its elements set to 0 for no unit at the current position, or 1 for a team 1 unit at the current position, 2 for team 2 etc. The paint method will take those numbers and draw pieces accordingly (change color for each type or whatever).
I hope that makes a bit of sense.
I'm doing a little strategy game to help me learn Java in a fun way. The thing is I visioned the units as objects that would self draw on the game map (using images and buffering) and would react to the mouse actions with listeners attached to them.
Now, based on some tutorials I've been reading regarding basic game programming, all seems to be drawn in the Graphics method of my Map class. If a new unit emerges, i just update the Map.Graphics method, it's not as easy as making a new Unit object which would self draw... In this case, I'd be stuck with a whole bunch of Map methods instead of using classes for rendering new things.
So my question is, is it possible to use classes for rendering units, interface objects, etc, or i'll have to create methods and just do some kind of structural programming instead of object oriented? I'm a little bit confused and I'd like to have a mental blueprint of how things would be organized.
Thanks!
Sounds like your objects need to have a common interface that they can all be down-casted to for rendering.
E.g. have a generic list of your interface type, populate it with the game objects, then enumerate the list and call the common method to do the rendering.
This is C# code, but it should be similar for Java
public interface IRenderable
{
void RenderMe(Graphics graphics)
}
List<IRenderable> myGameObjects;
foreach (IRenderable myGameObject in myGameObjects)
{
myGameObject.RenderMe(myMap);
}
While the objects are held in the list they can respond to events and update their internal state ready for the next render cycle.
As ck said, you could do this with a drawable interface, something like:
public interface GameElement {
public void draw(Graphics g);
}
public class Sprite implements GameElement{
private Image image;
private int x;
private int y;
public void draw(Graphics g) {
g.drawImage(image,x,y,null);
}
}
public class GameLoop {
public void drawElements(final Graphics2D g, final List<GameElement> elements) {
for (final GameElement gameElement : elements) {
gameElement.draw(g);
}
}
}
but the way you said you want to do it, with a listener, may give you problems in the future.
As dash-tom-bang already pointed, all elements are rendered in a single game loop, after all of them were already updated. If you do this with a listener and you have a game loop or any other thread modifying the unit list, you can end up with a concurrent access modification.
Besides, this way you will draw all elements in a single point, that will avoid some weird flickering on your game.
While "real" game projects come in many forms, ultimately you have something like this:
while True:
ProcessUserInput()
for o in objects:
o.Update()
for o in objects:
o.Render()
Use whatever mechanism you find dear to implement any and all of these functions. :) Polymorphism is fine, so you should feel free to use that if you're comfortable with that. The "world map" likely should be the first item in the list, unless your rendering system is sufficiently advanced to handle out-of-order drawing (depth sorting, basically).
From your question, it may be that the units are owned by the map? In that case, the Map.Render function would iterate over all of the units that it owns, calling Render on each one of them in turn. Regardless, it's probably cleanest if the code to draw a unit is in the class for that unit.
Good luck!
I'm developing a fair sized hospital simulation game in java.
Right now, my pain method is starting to look a little big, and I need a way to split it up into different sections...
I have an idea, but I'm not sure if this is the best way.
It starts by painting the grass, then the hospital building, then any buildings, then people, then any building previews when building. The grass and hospital building will not change, so I only need to paint this once. The buildings themselves won't change very often, only when new ones are built.
I was thinking, use boolean values to determine which sections need repainting?
Ideal, id like to be able to split up the paint method, and then call each one when needed, but I'm unsure how to physically split it up.
I am still quite new to java, and learning on the go.
Thanks in advance.
Rel
Another idea is to create a super class or interface for all items that must be drawn on the screen. Lets cvall this class ScreenObject. You can then have a draw(Graphics2d g) method specified in the ScreenObject class. Next, each object that must be drawn implements the draw() method and is only concerned about drawing itself. You can even consider creating a variable that determines whether this draw method should be run at all.
In the main class that paints the screen you can have a reference to all ScreenObjects in an ArrayList and your paint() method will simply iterate over this calling draw() on each object.
I'm assuming from your description that your scene is split up into tiles. Keeping an array of booleans is a good way to keep track of which tiles need redrawn on the next update. A LinkedList might perform a little better in some situations. (I'm thinking of a Game of Life simulation where there are tons of tiles to redraw and you need to check each neighbor, so you may not need to go this route.)
Without seeing your code I can't give very specific advice on splitting up your paint method. I can tell you that in sprite animations, each sprite object typically has its own draw method that takes the main Graphics object (or more likely a buffer) as a parameter. Since the sprite should know its own image and location, it can then draw itself into the main image. Your paint method can then just loop through your list of sprites that need to be redrawn and call their draw method.
You might look to Killer Game Programming in Java for more detailed information.
Well I am not really an expert at programming but to split up my paint method Ive always just made a new method that takes a Graphics object and call that from paint, it has always helped me to keep my code organized but I have never had a big project like it sounds you are working on so it might not work for your situation.