Allegro 5 drawing a bitmap over a primitive - c++

I've recently tried making an inventory system in allegro 5, where I draw a grid of squares 20x20 and drag-drop items around. The problem is, I can see the item sprite going under the actual grid that I drew, which is an unwanted effect. Here's my code:
if(draw)
{
draw = false;
al_draw_bitmap(image, item.posx, item.posy, 0);
if(mouseKey)
{
grab = true;
item.posx = mouse.posx - (item.boundx-5);
item.posy = mouse.posy - (item.boundy-5);
}
else if(mouseKey == false && grab == true)
{
for(int i = 0; i < mouse.posx; i += 20)
{
if(i < mouse.posx)
item.posx = i;
}
for(int j = 0; j < mouse.posy; j += 20)
{
if(j < mouse.posy)
{
item.posy = j;
}
}
grab = false;
}
for(int i = 0; i <= width; i += 20)
{
al_draw_line(i, 0, i, height, al_map_rgb(0, 0, 0), 1);
al_draw_line(0, i, width, i, al_map_rgb(0, 0, 0), 1);
}
al_flip_display();
al_clear_to_color(al_map_rgb(40,40,40));
}
(I know it's terribly written and un-optimized but I wrote it in about 10 minutes simply as a test)
How can I make it so the item sprite does not display the lines over it? Here's an example of my problem if I was too vague:
I'm using Codeblocks IDE on windows XP

Unless you fiddle with OpenGL settings, you're going to always get the things you draw last on top. So in this case, simply move al_draw_bitmap(image, item.posx, item.posy, 0); to be directly above al_flip_display().
Note that you will have some problems because you are manipulating item.posx and item.posy in that section, so you'd have to first cache the results:
int x = item.posx;
int y = item.posy;
// ...
al_draw_bitmap(image, x, y, 0);
al_flip_display();
However, that's just a bandaid over the larger problem: you shouldn't be changing anything inside your drawing block. The entire if/else block should be elsewhere. i.e.:
if (event timer is a game tick)
{
do all logic stuff
draw = true
}
if (draw)
{
do all drawing stuff
draw = false;
}

Related

I'm making a particle sandbox sand falling system in c++ sfml but I'm having some major performance issues

// spawn
if (Keyboard::isKeyPressed(Keyboard::Q)) // coal
{
particleR = new RectangleShape;
particleV.push_back(*particleR);
particleV[particleV.size() - 1].setSize(Vector2f(1, 1));
particleV[particleV.size() - 1].setFillColor(Color(55, 55, 55));
particleV[particleV.size() - 1].setPosition(Vector2f(worldPosI));
parID.push_back(1);
}
for (int i = 0; i < particleV.size(); i++)
{
if (parID[i] == 1) // checks if its coal
{
if (particleV[i].getPosition().y < 10) // checks if the particle is in air
{
particleV[i].move(0, 1);
for (int q = 0; q < particleV.size(); q++) // goes through each particle with each other and checks if some particle is inside
{
if (particleV[i].getPosition().x == particleV[q].getPosition().x && particleV[i].getPosition().y == particleV[q].getPosition().y && i != q)
{
particleV[i].move(0, -1); // if a particle is inside other particle, go up.
}
}
}
}
}
The problem is that, these for loops can not handle going through thousands of particles every frame and checking of they are colliding with each other. I wonder if there is a better another way of checking the interactions between particles.

How can I make my cellular automata quicker

I have a grid of 300x300 cells. I am checking each cell individually which means I am checking 90000 cells atleast every second. Now, I know, one second is pretty fast considering the cpu is going through 300^2 different cells. But this stuff just isn't fast enough. I watched a guy on youtube who got his simulation to update every 20 ms. And he was running 512^2 cells. How is this possible? Optimizations? Is my computer a potato? I'll show my code if anyone wants to see exactly what i'm doing.
for (int y = GY; y >= 0; y--)
for (int x = 0; x < GX; x++) {
cell* cell_pointer = &grid[x][y];
if (grid[x][y].CellT == type::SAND) {
if (grid[x][y+1].CellT == type::AIR) {
if (y+1 > GY-1) {
continue;
}
cell* cell_below = &grid[x][y+1];
cell_below->Color ={ 255,0,0 };
cell_below->CellT = type::SAND;
cell_pointer->Color ={ 0,0,0 };
cell_pointer->CellT = type::AIR;
}
else if (grid[x+1][y+1].CellT == type::AIR) {
cell* cell_below = &grid[x+1][y+1];
cell_below->Color ={ 255,0,0 };
cell_below->CellT = type::SAND;
cell_pointer->Color ={ 0,0,0 };
cell_pointer->CellT = type::AIR;
}
else if (grid[x-1][y+1].CellT == type::AIR) {
cell* cell_below = &grid[x-1][y+1];
cell_below->Color ={ 255,0,0 };
cell_below->CellT = type::SAND;
cell_pointer->Color ={ 0,0,0 };
cell_pointer->CellT = type::AIR;
}
}
}
The code above is my update function. I am updating the cells bottom to top, left to right. It's a sand simulation which is why we're checking the bottom left, bottom right as well as the bottom neighboring cells.
//Square//
SDL_SetRenderDrawColor(renderer, 0, 0, 255, 255);
SDL_RenderClear(renderer);
//////////
int X = floor(mousePos.x/r.w);
int Y = floor(mousePos.y/r.h);
if (left) {
grid[X][Y].CellT = type::SAND;
grid[X][Y].Color ={ 255,0,0 };
}
if (right) {
grid[X][Y].CellT = type::WALL;
grid[X][Y].Color ={ 0,255,0 };
}
for (int y = 0; y < GY; y++)
for (int x = 0; x < GX; x++) {
cell* cell_pointer = &grid[x][y];
SDL_SetRenderDrawColor(renderer, cell_pointer->Color.r, cell_pointer->Color.g, cell_pointer->Color.b, 255);
r.x = cell_pointer->PosG.x;
r.y = cell_pointer->PosG.y;
SDL_RenderFillRect(renderer, &r);
}
SDL_RenderPresent(renderer);
SDL_UpdateWindowSurface(window);
The code above is my draw function. I am using SDL as my graphics API. I am getting the mouse position relative to the grids so that when I click left or right mouse buttons I can draw a sand cell or a wall cell. So I am checking each cell individually top to bottom and left to right and then drawing a square individually where the cell's position is.

SDL_RenderDrawLines with a Ghost Line

I have a simple SDL2 window that i'm trying to draw a path on.
I can click ten times and draw out a line with this code
if (button == SDL_BUTTON_LEFT)
{
if (Path.size() == Clicks) return;
// Clicks is set by the initializer
// Path is a vector of SDL_Points
SDL_Point p;
p.x = x;
p.y = y;
Path.push_back(p);
}
SDL_Point *points = new SDL_Point[Clicks];
for (int i = 0; i < Path.size(); i++)
{
if (i == Clicks) break;
points[i] = Path[i];
}
SDL_RenderClear(ren);
SDL_SetRenderDrawColor(ren, 0, 255, 0, 255);
SDL_RenderDrawLines(ren, points, Clicks);
Which works fine, it allows me to draw a path with no issue, however, it creates a sort of ghost line that flies off the top of the screen.
Here's a picture of the line.
Is there anything I can do to get rid of this line and use SDL_RenderDrawLines? If not what call should I use?
to me it looks more like a problem with the parameters for SDL_RenderDrawLines()
Have you checked the size of points and the value of Clicks?

Draw multiple objects in D3D12

I am tinkering with DirectX 12 and have hit a wall while trying to draw a "checker board." I have search the net quite a bit, so any help/pointers will be appreciated.
In D3D11 the working code is as follows.
auto context = m_deviceResources->GetD3DDeviceContext();
for (int i = -10; i < 10; i++)
{
for (int j = -10; j < 10; j++)
{
// perform translation
XMStoreFloat4x4(&m_constantBufferData.model, XMMatrixTranspose(XMMatrixTranslation(i, j, 0.0f)));
context->UpdateSubresource(
m_constantBuffer.Get(),
0,
NULL,
&m_constantBufferData,
0,
0
);
// shaders, etc...
// draw the square
context->DrawIndexed(
m_indexCount,
0,
0
);
}
}
In D3D12, I have tried doing the same thing, but it appears to be performing the translation globally, as all square are in the same location.
bool Sample3DSceneRenderer::Render()
{
if (!m_loadingComplete)
{
return false;
}
DX::ThrowIfFailed(m_deviceResources->GetCommandAllocator()->Reset());
DX::ThrowIfFailed(m_commandList->Reset(m_deviceResources->GetCommandAllocator(), m_pipelineState.Get()));
PIXBeginEvent(m_commandList.Get(), 0, L"Draw the objects");
{
m_commandList->SetGraphicsRootSignature(m_rootSignature.Get());
ID3D12DescriptorHeap* ppHeaps[] = { m_cbvHeap.Get() };
m_commandList->SetDescriptorHeaps(_countof(ppHeaps), ppHeaps);
CD3DX12_GPU_DESCRIPTOR_HANDLE gpuHandle(m_cbvHeap->GetGPUDescriptorHandleForHeapStart(), m_deviceResources->GetCurrentFrameIndex(), m_cbvDescriptorSize);
m_commandList->SetGraphicsRootDescriptorTable(0, gpuHandle);
D3D12_VIEWPORT viewport = m_deviceResources->GetScreenViewport();
m_commandList->RSSetViewports(1, &viewport);
m_commandList->RSSetScissorRects(1, &m_scissorRect);
CD3DX12_RESOURCE_BARRIER renderTargetResourceBarrier =
CD3DX12_RESOURCE_BARRIER::Transition(m_deviceResources->GetRenderTarget(), D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET);
m_commandList->ResourceBarrier(1, &renderTargetResourceBarrier);
D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView = m_deviceResources->GetRenderTargetView();
D3D12_CPU_DESCRIPTOR_HANDLE depthStencilView = m_deviceResources->GetDepthStencilView();
m_commandList->ClearRenderTargetView(renderTargetView, m_colors.Get_background(), 0, nullptr);
m_commandList->ClearDepthStencilView(depthStencilView, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr);
m_commandList->OMSetRenderTargets(1, &renderTargetView, false, &depthStencilView);
m_commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
m_commandList->IASetVertexBuffers(0, 1, &m_vertexBufferView);
m_commandList->IASetIndexBuffer(&m_indexBufferView);
for (float i = -10.0f; i < 10.0f; i++)
{
for (float j = -10.0f; j < 10.0f; j++)
{
// as far as I know, this is how I should perform the translation
XMStoreFloat4x4(&m_constantBufferData.model, XMMatrixTranspose(XMMatrixTranslation(i, j, 0.0f)));
UINT8* destination = m_mappedConstantBuffer + (m_deviceResources->GetCurrentFrameIndex() * c_alignedConstantBufferSize);
memcpy(destination, &m_constantBufferData, sizeof(m_constantBufferData));
m_commandList->DrawIndexedInstanced(6, 1, 0, 0, 0);
}
}
CD3DX12_RESOURCE_BARRIER presentResourceBarrier =
CD3DX12_RESOURCE_BARRIER::Transition(m_deviceResources->GetRenderTarget(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
m_commandList->ResourceBarrier(1, &presentResourceBarrier);
}
PIXEndEvent(m_commandList.Get());
DX::ThrowIfFailed(m_commandList->Close());
ID3D12CommandList* ppCommandLists[] = { m_commandList.Get() };
m_deviceResources->GetCommandQueue()->ExecuteCommandLists(_countof(ppCommandLists), ppCommandLists);
return true;
}
Thank you,
Chelsey
You're just writing your translation matrix to the same piece of memory for every copy of the model. Since the GPU hasn't even begun drawing the first model by the time you've finished writing the translation matrix for the last one, the only place any of these models are going to draw is at the place of the last translation matrix written.
You need to write each matrix to a separate, distinct location in memory and ensure they're not overwritten by anything else until the GPU has finished drawing the models.
The act of calling DrawIndexedInstanced does not immediately instruct the GPU to draw anything, it merely adds a command to a command list to draw the object at some time in the future. If you're not familiar with the asynchronous nature of Graphics APIs and GPU execution you should probably read up a bit more on how it works.

c++ card game, hand being dealt more than once when a new round deck is created / new round is started

I'm writing a video poker game and I'm having a problem with a hand being drawn and then replaced when a new round is started.
The idea is you start with five cards, you select which cards to keep and then the others are switched out when you click "deal", you will then be shown your new cards and told what you've won, after that you will be asked to start a new round, when you click "new round" the deck that was used previously should be discarded, a new hand taken from that deck and then drawn onto the screen.
The first two things work, the problem is that when I click "new round" it very quickly draws the hand to the screen and then replaces it with another hand, this doesn't effect the players bet, the money they have, absolutely nothing, it took me a while to notice that it was actually happening.
I can't post a working example, that would require the entire game to be uploaded (my code isn't very elegant) but I will try to show the relevant text.
Main:
int main(int argc, char *argv[])
{
srand(time(NULL));
//load static cards
SDL_Surface* deal_card = load_surface("resources/images/cards/misc/deal.png");
SDL_Surface* round_card = load_surface("resources/images/cards/misc/new_round.png");
SDL_Surface* held = load_surface("resources/images/cards/effect/held.png");
//initiate standard sdl modules
if(!init())
{
printf("fail init");
}
//initiate SDL_ttf
else if(TTF_Init() == -1)
{
printf("TTF INit fail");
}
else
{
//should exit
bool quit = false;
//events
SDL_Event e;
//font and font colour to be used for rendering text1
TTF_Font* font = TTF_OpenFont("resources/fonts/OpenSans-Regular.ttf", 18);
SDL_Color text_colour = {236, 251, 100};
//create a new deck, draw out a hand, sort it numerically, setup images and positions for cards
vector<card>my_deck = new_shuffled_deck();
vector<card>my_hand = hand(my_deck);
sort_hand(my_hand);
setup_hand(my_hand);
//should switch cards that are not held and remove those used
//must be TRUE on start otherwise the first deal will duplicate cards
bool switch_hand = true;
int round_number = 1;
//get or set bet information
read_bet(player_pot, cash_borrowed);
while(!quit)
{
//starting mouse position
int mouse_x_pos = 0;
int mouse_y_pos = 0;
//push current mouse position to starting mouse positions
SDL_GetMouseState(&mouse_x_pos, &mouse_y_pos);
//set up to blit hold icon
update_hold_position(my_hand);
//check for winning hand
winning_hand hand_details = my_scores.card_check(my_hand, bet_amount);
//setup render and blit text
render_and_blit_text(font, hand_details, player_pot, cash_borrowed, text_colour);
scoring_text(font, hand_details, text_colour);
//switch out cards that are not held
if(switch_hand == true)
{
swap_cards(my_hand, my_deck);
}
switch_hand = false;
while(SDL_PollEvent(&e) != 0)
{
if(e.type == SDL_QUIT)
{
quit = true;
}
if(e.type == SDL_MOUSEBUTTONDOWN)
{
//set mouse position to carry over without resetting
int n_mouse_pos_x = mouse_x_pos;
int n_mouse_pos_y = mouse_y_pos;
//check if card is clicked, if is selected de-select, if not selected then select
for(size_t cpc = 0; cpc < my_hand.size(); cpc++)
{
// if mouse position is in range of left side of card and right side of card
if(n_mouse_pos_x > my_hand[cpc].position.x and n_mouse_pos_x < my_hand[cpc].position.x + my_hand[cpc].image->w &&
n_mouse_pos_y > my_hand[cpc].position.y and n_mouse_pos_y < my_hand[cpc].position.y + my_hand[cpc].image->h)
{
//if clicked un-click, if un-clickde click
if(my_hand[cpc].selected == 0)
{
my_hand[cpc].selected = 1;
}
else if(my_hand[cpc].selected == 1)
{
my_hand[cpc].selected = 0;
}
}
}
//if deal is clicked
if(n_mouse_pos_x > deal_rect.x and n_mouse_pos_x < deal_rect.x + deal_card->w &&
n_mouse_pos_y > deal_rect.y and n_mouse_pos_y < deal_rect.y + deal_card->h)
{
//switch held cards, if last round switch entire hand, update cash
deal_clicked(switch_hand, round_number, my_hand, my_deck, cash_borrowed, player_pot, amount_won,
bet_amount, hand_details);
}
}
}
//blit section
//blit cards to screen
blit_cards(my_hand, round_number, held, screen_surface, deal_rect, round_card, deal_card);
SDL_Surface* fill_screen;
fill_screen = SDL_CreateRGBSurface(0, screen_width, screen_height, 32, 0, 0, 0, 0);
SDL_UpdateWindowSurface(window);
SDL_FillRect(screen_surface, 0, SDL_MapRGB(fill_screen->format, 18, 17, 233));
SDL_FreeSurface(fill_screen);
SDL_Delay(30);
}
}
close();
return 0;
}
Swap cards:
void swap_cards(vector<card>&my_hand, vector<card>&my_deck)
{
for(size_t b = 0; b < my_hand.size(); b++)
{
if(my_hand[b].selected == false)
{
SDL_FreeSurface(my_hand[b].image);
//replace card with card of the same index from the deck
my_hand[b] = my_deck[b];
// remove card from deck so it cannot be chosen again
my_deck.erase(my_deck.begin() + b);
}
else
{
// this prevents memory leak on held cards, no idea why.
SDL_FreeSurface(my_hand[b].image);
}
}
//set up images and position for cards again
setup_hand(my_hand);
}
Deal clicked:
void deal_clicked(bool &switch_hand, int &round_number, vector<card>&my_hand, vector<card>&my_deck,
int &cash_borrowed, int &player_pot, int &amount_won, int& bet_amount, winning_hand &hand_details)
{
switch_hand = true;
round_number++;
// aka if(round_number % 2 == 0 and round_number != 0)
if(round_number == 3)
{
//free card surface images
for(size_t d = 0; d < my_hand.size(); d++)
{
SDL_FreeSurface(my_hand[d].image);
}
vector<card>().swap(my_deck);
//replace deck with new deck
my_deck = new_shuffled_deck();
//draw new hand
vector<card>().swap(my_hand);
my_hand = hand(my_deck);
//sort hand by card number
sort_hand(my_hand);
//load images and position cards
setup_hand(my_hand);
//set round number back to beginning
round_number = 1;
//distribute winnings and take next bet amount
amount_won = hand_details.hand_score;
if(cash_borrowed > 0)
{
cash_borrowed -= amount_won;
}
else if(cash_borrowed < 0)
{
player_pot += abs(cash_borrowed);
cash_borrowed = 0;
}
else
{
player_pot += amount_won;
}
if(player_pot <= 0)
{
cash_borrowed +=5;
}
else
{
player_pot -= bet_amount;
}
write_bet(player_pot, cash_borrowed);
}
}
Hopefully that should be enough for someone to have an idea about where my problem is coming from.
If anyone wants more code I can post it, it jut gets even more messy, these are the only areas I think could be causing the problem, then again I can't figure out what it is.
EDIT:
Solved, duplicate call to the setup_hand function.
Duplicate call to setup_hand function.