I am trying to write a card game, where a player is able to stack cards. E.g. Ace, Two, Three.
I would like to visualize a stack of cards, where the Ace card is partially covered by the Two card, and the Two card is partially covered by the Three card. The Three card is completely visible.
Easy, I thought. I make a user control where I add my cards: Controls.Add(ace); Controls.Add(two); etc.
Then I need something that is able to lay-out my Controls, so I wrote my custom LayoutEngine (derives from LayoutEngine). My first test does nothing more then shift the control 50 pixels.
After running the solution I noticed that the Z-ordering was wrong. Instead of the Three card being on top, the Ace card was on top looking like this:
Ace Card > Two card > Three card where:
Ace Card is on top
Two Card is under the Ace Card
Three Card is under the Two Card.
So I started looking for a way to change the Z order in WinForms and found out that it is simply "not available". Like.. Huh?!
The alternative (provided by MS) is that the Z order can be altered, by setting the ChildIndex for the Controls. Jikes, that means that poking around in a list, change the behaviour of my application. Way to go MS...
Anyway, I tried all kind of things, but it seems impossible to write a layout engine that does the trick.
I've google-d all day, and found nothing useful. I am no GUI expert, so I run stuck on this lame issue. Who can help me out?
Much appreciated!
Bas
Your best bet is to avoid the use of controls entirely. They will A) result in poor(er) performance and B) complicate hit testing/drawing.
Simply create objects to represent the state of the table (I use a CardContainer object) and use Graphics.DrawImage to draw all of the cards where they lie during the paint event. You can use a single control for the entire table if you need to also add other UI elements.
This will also make animating card movement simpler should you decide to add animation.
Updated
I meant to expand this answer but was called away and simply posted what I had. Here are some details you may find useful. I created a "solitaire game engine". The engine hosts one solitaire game at a time (klondike, spider, strategy, etc.). It tracks statistics for each game and allows both playing and editing of the individual games. The games are IronPython scripts which makes adding new games relatively easy.
My CardContainer is an object that holds zero or more cards.
It has a LieDirection (None, Up, Down, Left, Right) which determains how its cards are laid out.
It has a MaximumDepth that clamps the number of cards drawn in the LieDirection. This is handy for games like Klondike where you only want to show the top 3 cards of the waste.
It has properties for spacing the cards. There are separate spacing values for cards that are face up and face down. It can auto-pack cards into an area defined by MaximumLength. And it has an 'extra pad' value, one for each card--whether there is a card at that index or not. The latter is used during a simulated mouse hover to 'uncover' the card pointed to so that the user can clearly see a card that might be obscured by cards on top of it. This is accomplished by setting the 'extra pad' of the card on top of the hover card. This could have been simplified by having a "hover card" and "hover spacing" property, but having extra padding per-card allows for odd kinds of solitaire games that highlight a particular 'row' in the tableau piles with spacing.
It has a HitTest method to return a Card from a given X,Y location.
All of that means that the Card object has no notion of where it is drawn on the table. I have a complex animation system and so a card's location ultimately comes from the animation engine. If a card is not currently animating, the animation system gets its location from its container.
Note that the card's location referred to above is strictly for drawing. All cards are always attached to exactly one CardContainer and are simply moved from one to another. There is one 'special' container called the Deck which initially contains every card. It is positioned off of the table initially. A container has a Visible property. Animations play only if moving a card from a Visible container to another Visible container. This allows you to move cards around without animation when necessary and cards can "fly out" to/from containers positioned off the table.
The engine also has a rudamentary layout system for positioning CardContainers relative to each other. One very handy thing I did was to use a card-size-relative coordinate system. The 'width' of the table is exactly 11 card widths. No matter how big the user sizes the table, the width is always 11 card widths. This means that the card sizes (as viewed by the user) grow and shrink. The height is variable, but is determained by a fixed card-sized ratio (determained from the card bitmaps). If you give a CardContainer an X value of 1.0, that means it will be located one card-width from the left of the table. The values are floating points so you can specify 1/2 a card-width with 0.5. This makes it very easy to position elements in the script without having to worry about screen coordinates. No matter how the user alters the size of the screen, your game will be laid out exactly the same way.
The engine also has unlimited undo and redo. This means that not only do card moves (from one container to another) have to be recorded, but all property changes are recorded as well (both card and container properties). Undo and redo can be difficult to implement if not planned for from the start. The scripts have access to a Game.LogVariableChange method so that they can alter the value of a global variable through the recording mechanism. This is necessary for something like Klondike's "three redeals" feature. The script has to store the number of redeals used, but if the user undid a redeal, that variable's value change has to be undone too.
This works very well for Solitaire, but could work for just about any kind of card game. Obviously you don't have to go and implement all of this your first time out. I present the information just to give you some ideas.
Related
I'm working on a project where I'm trying to implement Q-learning in C#(Unity specifically). I have a car which needs to drive along a grid path, like shown:
Example - Where Green is goal(+reward), gray and off-grid are obstacles(-reward) and blue is the car. I've been looking at a few examples/guides on how to implement this (pseudo-code mostly), but they seem to know a pre-defined grid to work(A reward grid), which I'm unsure how to implement in my scenario.
The idea is that my car have three states & actions:
States: Driving in left lane, driving in center lane, driving in right lane
Actions: Move one up and left, move one up and right, move one up
I'm trying to follow this: http://mnemstudio.org/path-finding-q-learning-tutorial.htm and adapt that into my system - but I fail to see how to do the adaption. Wouldn't this require my Q-matrix to be much`much larger, as each cell would be an individual state? Lets say my track is 16 cells long, with 3 lanes, would this mean I should have a 48 states * 3 actions grid?
Edit: To simplify my post, I thin what I'm struggling with is how to connect my environment and my Q-matrix, so I can modify my q-matrix values depending on the behaviour of my agent in my kind of system.
Typically, in grid-based environments like your car example, each cell corresponds with a different state. So, your environment may have the 3 actions you described (move one up and left, move one up and right, move one up), but definitively doesn't have three states.
As you point in the last part of the question, if your track is 16 cells long and 3 lanes, your environment should be modelled with 16 * 3 = 48 states. Therefore, your Q-matrix size should be 48 x 3.
With this setup, you can easily map your agent state (car position in the track) with the Q-matrix.
So I created this window editor in WPF that helps me create Forms quickly. Now, one feature I've worked on was create a guideline tool. At its core it's just creates lines to help keep my UI elements organized on the screen. I will show you an example. The long black lines are the guidelines I spoke about earlier.
Now, I noticed that in a lot of art programs (i.e Photoshop) and popular IDEs that implement Forms that they have a "snap-to" feature where a UI element will snap to a line UI or to another UI element in order to maintain alignment. Something like this:
I already have the guidelines showing up in my editor. Now, what I would like help understanding is, how would I go about implementing the "snap to" feature? I'n not asking for code, just a breakdown (a visual breakdown will be most welcomed).
These are my questions:
How does an object know if one of its edges (top, bottom, left, right) touched a line?
How would I know how to unsnap the UI element if the user keeps moving the mouse past the guideline?
If I have (say) 10 lines how do I make sure that the object attaches to the nearest line(s)?
UPDATE
When an object moves or is resized, keep track of its actual size/location relative to the mouse, and separately keep track of a snapped version of the same information. If a given actual edge is within some arbitrary distance of a line -- say 4 pixels (arbitrary WPF units, really). If it's within that distance, set it to the value for the line it's close to. You still have the actual mouse-relative values as well, so you know to unsnap it if the the user keeps on dragging it and it leaves that 4-unit zone.
When an object is being resized, at most two edges of the bounding box will be changing position (assuming you can drag corners as well as edges). When you're moving an object, all four edges of the bounding box will move.
So you need to keep track of which edges are moving, and only do snap-line proximity testing on those edges. When you're moving an object, snapping the left or top edge to a line is easy. That's just the position of the object. But if you snap the right or top edge to a line, you're setting
snappedPos.X = nearestVerticalSnapLine.X - draggedObject.Width;
or
snappedPos.Y = nearestHorizontalSnapLine.Y - draggedObject.Height;
You may also have cases where opposite edges will both be in proximity to lines: Say you're dragging a seven-unit square across a ten-unit grid. When it's inside a grid box, all four sides will be in proximity to a grid line. Which wins? The closer one.
Locating the snap lines is easy -- %.
using a file I want to create a map and I am wondering about the best approach doing so.
Actually I searched the forum but I only found map generation algorithms that randomly creates maps.
Let's look at a minimal example.
e.g. Ihave a file containing
0110
1001
1000
0000
Every 0 shall be water and every 1 shall be earth.
I would handle this by simply havin two different bitmaps and loading them at the right coordinates. That'd be simple.
But let's guess we have a 1000*1000 big map and there is only enough space for 16*16 tiles per frame. Then I'd get the current position and would build the map around it.
Assuming we can only display 3*3 tiles, using the minimal example and being at position (2,2) where x and y is element 1..4 so what the user could see at this time would be:
011
100
100
Solution
I thought about using a text file, where a line represents the x-coordinate direction and
a column represents the y-coordinate direction. The whole file is being loaded at the beginning of the program. This shouldn't use too much ram assuming 1 tile needs 1 byte, what should be enough.
For redrawing the map when the user is moving, I'd get the moving direction and slide the current Bitmap for the height/width of a tile in the opposite direction and only look up the bitmaps for the new blank spaces. So I only need to look up the tile information for m+n-1 (where m is the amount of displayed tiles in y and n in x direction) tiles (max case if moving diagonal) instead of loading m*n tiles everytime the user moves.
Example
I created an example to make the above given example more easily to understand.
this is the whole map:
We can only display 3*3 tiles and the user is at position (2,2) so what we'd actually see is:
now he is moving towards the bottom right corner:
and the black framed section is being move to the opposite direction, so that we get:
now the blank tiles (black framed white areas) have to be looked up and teh final result will be:
Question
is this a good way of building a map? Or are there much faster functions, maybe already implemented in the microsoft xna-gamestudio package ?
I would pre-fetch 1-2 tiles range outside the screen view, so that you won't have weird pop-up as the player move.
But if your game is a top-down tile game, this solution is quite conservative. In most hardware today, you could create a very big range around the player without problem. Just look at the number of block Minecraft can process and display. Since you are reusing the same texture, you just load the asset once and reuse them in a tile, which would probably an object with very little memory footprint.
Have you tried implementing it yet?
I am developing a card game using WPF and since i do not have any knowledge about animations i would like to know if someone could help me in how to write an animation to simulate a Card ( Image ) been played over a table.
At the bottom and top of my game table i have my cards on vertical position.
At the right and left my cards are on horizontal position.
What i really want is give an impression that a human is selecting and throwing the card.
Since your question is pretty open-ended, I'll give you an open-ended start...
Look into Storyboards, and how to use the same to modify the RenderTransform of your Card UserControl.
Your first step should really just be animating your card's position from its initial spot to the center of the table. As an additional hint (which will come in handy after you've learned about Storyboards), your DoubleAnimation.From property does not need to be specified. You just need to specify the DoubleAnimation.To property.
I see questions like this all the time on SO, and it really does give the impression of "I haven't tried, and I have not read anything". You already have your cards on the table (so to speak), and the question is, make it look like a human did it.
There are a variety of ways, some cheap and simple, some more complex and involved. You won't know the answer until you try.
For example, perhaps you want a card to go from one position to another (optionally flipping). You have varying degrees of difficulty here:
Move the card to the position, as is. Cheap and easy. You could even use the distance between the source and the target to determine the speed to have some kind of residual momentum.
Cards are at different angles. How do we rotate? XNA makes this pretty simple, have you looked up on XNA and general rendering? Or do you want to this purely using WPF?
Does the move involve showing the card face-up, or not? Will there be an animation involved? Are you happy with just the face changing or do you want to see an actual "flip"? If it's the latter than some kind of a plane in XNA using 3D might be better, at least then you can have two faces with two different textures.
What I am saying is, and why this is an answer as opposed to a comment, is that you have given no indication of anything that might be considered trying to solve the problem. You seem like you've got halfway there, you've already got cards rendered on the screen. But to ask "Make it look like a human put a card in"...? Well, sorry... it's not that simple. You can make this task as easy or had as you wish.
I have to modify a WPF application written in C# that displays a complex 3D model with many sub-models or parts. When the user selects a part via an alternate user-interface mechanism, I'd like to rotate, scale, or move the scene so that the sub-model comes into view. No sub-model is completely hidden (i.e. interior to the main model).
What's the best way to do this?
As further information, there is no real top or bottom to the model. It is a 3D representation of a molecule, and the user selects an atom that needs to "scroll into view."
Get the center (or centroid) of the bounding volume of the submodel. Rotate the camera to look at the center. Move or zoom the view until such that the submodel bounding volume occupies a predefined portion of the screen. This involves solving a simple linear equation relating the viewing volume and the bounding volume. It's fairly easy if your bounding volume is a minimum-bounding-box.
EDIT
In that case you may be better off if you do some googling first. The specific feature you're talking about is usually called 'zoom to fit'. If you do some googling I'm sure you'll find some in-depth discussion of implementations, that will do far better than I could here. The explanation requires you understand things like transformations between screen coordinates and world coordinates and how they are related.