I am working on a window which displays a number of objects (a graph) (C++/Win32API). This is in GDI+ and I have written a test piece of code with Direct2d as I want to improve the performance when dragging objects in the window. The best approach I have found (to date) is the following (using a graph of 1000 nodes and 999 edges).
(bascially buffer static content to a bitmap buffer and only draw whats moving)
When dragging starts (e.g lbuttondown state), create a base rendertarget with the full graph excluding the node being dragged and the attached edges, call GetBitmap and store for later use. When I need to draw (due to mousemove event and lbuttondown state true), then clear the current hwndrendertarget (background wash white), then draw the edges that are connected to the node being moved into the hwndrendertarget, then copy the save bitmap to the hwndrendertarget, then copy the node bitmap (created when the node is first created in the DB, saves actually drawing it) being moved to the hwndrendertarget, then call EndDraw.
Now this works ok (ish), what I don't like it that, when the node is dragged quickly the mouse cursor moves ahead of the node being dragged (distance depending on speed of drag/mousemove bu worst case up to about 1/2 inch). My reference app is MS Visio, dragging a single object on this shows the cursor staying in the same position over the object being dragged maybe +/- 1/2 pixels.
What I have not tried yet is moving all the (and only) the drawing operations to a separate thread, but before I try this I would like to research other methods if other single threaded approaches would trump this way.
Update:
I have optimized this a bit more with improvement, I found I was allocating and de-allocating the edge brush in the draw function which I have moved out to a class wide object and initialize for the life of the class as with other brushes etc. The cursor now only gets a little way (2 pixels or so) outside of the object being dragged when being dragged quickly, the object is a 15px radius circle. so the cursor is able to move up to 17px away from the middle of the object (the point the cursor should stick to) when being dragged. In testing I found an interesting thing, on my main monitor the drag is worse in that the cursor can get ahead of the object being dragged by more than 17px, say up to maybe 25px from the center point of the object where the cursor should be fixed. On the second monitor for the extended desktop (i.e. no taskbar) the drag is better in that described previously. If I hide the taskbar on the main monitor and run the app on that monitor and drag, the performance is the same as the second monitor.
Related
I am currently working on a new RPG game using Pygame (my aim here is really to learn how to use object oriented programming). I started a few days ago and developed a movement system where the player clicks a location and the character sprite goes to that location and stops when it get's there by checking if the sprite 'collides' with the mouse position.
I quickly found however that this greatly limited the world size (to the app window size).
I started having a look into making a movement system where the background would move with respect to the player, hence providing the illusion of movement.
I managed to achieve this by creating a variable keeping track of my background map position. The map is much bigger than the app window. And each time I want my player to move I offset the background by the speed of the player in the opposite direction.
My next problem now is that I can't get my character to stop moving... because the character sprite never actually reaches the last position clicked by the mouse, since it is the background that is moving, not the character sprite.
I was thinking of spending some time coding in a variable that would keep track of how many displacements it would take the character sprite to reach the mouse clicked position if it was to move. Since the background moves at the character sprite's speed it would take as many displacement of the background in the x and y directions to center the clicked position on the background to the character sprite at the center of the screen.
It would be something like that:
If MOUSEBUTTON clicked:
NM = set number of moves needed to reach the clicked position based on character sprite distance to click and character sprite speed.
If NM != 0:
Move background image
Else:
pass
This would mean that when my background has moved enough for the character sprite to now be just over the area of the background that was originally clicked by the player, the movement would stop since NM == 0.
I guess that my question is: Does that sound like a good idea or will it be a nightmare to handle the movement of other sprites and collisions ? And are there better tools in Pygame to achieve this movement system ?
I could also maybe use a clock and work out how many seconds the movements would take.
I guess that ultimately the whole challenge is dealing with a fixed reference point and make everything move around it, both with respect to this fixed reference, but also to their own. e.g. If two other sprites move toward one another, and the character of the player also "moves" then the movement of the other two sprites will have to depend both on the position of the other sprite and also on the offset of the background caused by the movement of the player's character.
An interesting topic which has been frying my brain for a few nights !
Thank you for your suggestions !
You actually asking for an opinion on game design. The way I look at it, nothing is impossible so go ahead and try your coding. Also it would be wise to look around at similar projects scattered around the net. You may be able to pick up a lot of tips without re inventing the wheel. Here is a good place to start.
scrolling mini map
First of all don't think I'm making a "SFML and/or C++ performance Issue" type question. I'm not satisfied with the performance of this map editor I've been working on and I'm 99% percent sure I'm at fault for it.
Currently how I place tiles on the map is basically I have a function that loops through every single tile on the map and checks if the mouse is hovering over it. I call this function inside another function simply titled handleMouseClick()
This is plenty functional if you were just clicking each time you wanted to place a tile, however I have it sort of like a paintbrush. Even if there's only 500 tiles on the map, it will skip tiles if you drag it across the screen quickly. I need to be able to create maps that have 5000+ tiles and I can't afford so-so performance.
I've looked over my code and made sure I'm not making unnecessary copies. I'm pretty sure that the best way to increase performance would be to change how I check which tile the mouse is changing.
The only idea I have is to have the map in "chunks" so that it will check the tiles of the "chunk" the mouse is in.
Use math. Lets say you have tiles with pixel dimensions {tile.width, tile.height}. And your application's window is a view of the map, and the top left corner of the window is on pixel {view.x, view.y}. And the mouse position, relative to the top left corner of the window is {mouse.x, mouse.y}. You can calculate which tile the mouse is pointing to with the following:
transformed_mouse.x = mouse.x + view.x;
transformed_mouse.y = mouse.y + view.y;
mouse_tile.x = transformed_mouse.x / tile.width;
mouse_tile.y = transformed_mouse.y / tile.height;
For handling a dragging effect where the event system doesn't update fast enough, keep track of where the mouse was for the previous iteration, and use Bresenham's line algorithm to fill in all the tiles between the tile which the mouse is currently pointing to, and the tile which the mouse was pointing to previously.
This is related to one of my other questions.
If I am tiling a large image by creating a separate QGraphicsItem (with the raster data as its pixmap), how do I keep track of the QGraphicsItem's position within the scene? Obviously for raster data, it is important to keep all the tiles "touching" to make a continuous image and they also have to be in the right place so the image doesnt look jumbled.
Does each tile have to have positioning methods that move it in relation to it's neighbors on the top/left/bottom/right? This seems kind of clunky. Is there a better way to make them all move together?
In other words, if I pan the scene with scroll bars, or pick up the image and drag/move it around in the scene, I want all the tiles to also move and stay in the right position relative to each other.
What is the best approach for controlling the layout, which tiles need to be rendered (i.e. only the visible ones), and populating the data only once it is needed? Also, once a tile has been rendered, is the data from it ever dropped, and repopulated from the image file, say if it stays out of view for a while, then comes back later if someone pans to that section?
There are (more than) 2 ways of doing this:
Use QGraphicsItemGroup which
handles grouping of your tile items
for you. It moves, selects, updates
it's group members as if they are
one. I've never used it but from the
doc, it seems to work with typical
applications.
Paint the tiles yourself in the
paint() of one custom item. This
gives you total control on how to
place and draw the tiles while the
item truly acts as one item since it
is, well, one item. This is what I
do.
I have designed a small tutorial named "Stacker", As the name suggests, The game involves stacking blocks on each other. I have a large number of blocks to be stacked and hence all cant be accomodated in the screen itself... I m new to cocos2d and box2d but have managed to create a body with its adjoining sprite wen a user clicks on the screen. I have used MouseJoint to give movement to the body till the user performs the drag action that is till the user takes his finger off the screen.
The problem is that i need to follow the sprite (actually need the camera to follow the sprite) when the user drags it above the screen space, i referred the following links with no success... i guess wat i need is to move the body to a virtual coordinates which m not getting coz even if the screen does shift using the camera methods, but the sprite doesnt move with respect to the screen...
cocos2d forum link
flash concept but box2d
Can some1 guide me in case i need to have some pre-requisites before following camera in the manner i specified.. Thanx!
Ok Guys!
Got it guys! Had to take a global variable which records the increments per frame, The increments were equal to the layer movement which i did by setting the position of the layer to a unit less in every frame! Then set the Mouse join to the target which is (ScreenCoordinates + increment) dis too has to be done in every frame!
Done!
Cool method but needed a bit of brainstorming!!
I'm currently writing a c++ console application that grabs the mouse position at regular intervals and sends it to another visual application where it is used to drive some 3d graphics in real time. The visual app is closed source and cannot be altered outside it's limited plug-in functionality.
Currently I'm using the GetCursorPos() function which is easy and fast enough, but I'm running into the issue that all of the data is clipped based on the current screen resolution of 1920x1600 so that all x values are between 0 and 1920 and all y values are between 0 and 1600 no matter how far the mouse is physically moved.
I need to get the mouse position before it's clipped at the edge of the screen, or possibly the deltas which I could use to calculate the current position.
I've seen some references to the windows MouseMove event but I would really not want to implement a window to make it work or especially have it as the active to receive those events.
I'm working in a windows environment and a language change is not feasible.
I might be wrong, but in Win32 land you don't get mouse move messages when the mouse is at the edge of the screen because, well, the mouse isn't moving. The usual way to get an infinite mouse area is to do the following:
Hide the mouse, get exclusive access and record position
Centre mouse to window
When mouse moves, get delta from centre of screen to current position
Centre mouse to window again
The next mouse move should have a delta of (0,0), so ignore it
Go to 3 until end of mouse move operation
Reset position, show the mouse and release exclusive access
If you didn't hide the mouse, then you'd see the mouse moving a small distance and then snapping back to the centre position, which looks nasty.
This method does require a message pump for the mouse move messages so the console application idea probably won't work with this. Can you create a full screen invisible window for grabbing the mouse?
Just get the position, and move it to the center and return the delta yourself
This is how FPS games do it
I don't have any direct experience with raw input, which is probably what you need to tap into. According to MSDN, you have to register the device, then setup your winproc to accept the WM_INPUT messages and then do your calculations based on the raw data.
Here's another relevant link.