Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Sprites not showing up?  (Read 3861 times)

0 Members and 1 Guest are viewing this topic.

MatsVed

  • Newbie
  • *
  • Posts: 7
    • MSN Messenger - afr088@hotmail.com
    • View Profile
Sprites not showing up?
« on: January 19, 2011, 03:31:05 pm »
I've been following the Sprite tutorial and the tutorial about integrating with Win32. I've made my code compile and whatnot, but all I get is a white window!

Code: [Select]
// TSO GUI.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "TSO GUI.h"
#include "UIScene.h"
#include <SFML/Graphics.hpp>

#define MAX_LOADSTRING 100

// Global Variables:
HWND  g_hWnd; // The application's window.
HWND  m_SFMLWindow; // The SFML window.
sf::RenderWindow m_SFMLView; // The SFML renderwindow.
HINSTANCE hInst; // current instance
TCHAR szTitle[MAX_LOADSTRING]; // The title bar text
TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name

UI::UIScene TestScene("gamedata\\uiscripts\\personselection.uis");

#define WINDOW_WIDTH 800 // Preferred width of the app
#define WINDOW_HEIGHT 600 // Preferred height of the app

// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);

  // TODO: Place code here.
MSG msg;
HACCEL hAccelTable;

// Initialize global strings
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_TSOGUI, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);

// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}

//InitDirect3d();

hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TSOGUI));

// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
m_SFMLView.Clear();

TestScene.Draw(&m_SFMLView);

m_SFMLView.Display();
}
}

return (int) msg.wParam;
}

//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
//  COMMENTS:
//
//    This function and its usage are only necessary if you want this code
//    to be compatible with Win32 systems prior to the 'RegisterClassEx'
//    function that was added to Windows 95. It is important to call this function
//    so that the application will get 'well formed' small icons associated
//    with it.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;

wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TSOGUI));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_TSOGUI);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

return RegisterClassEx(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Store instance handle in our global variable

   g_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0,
  WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL, hInstance, NULL);

   DWORD Style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS;

   m_SFMLWindow = CreateWindow((LPCWSTR)"STATIC", NULL, Style, 50, 100, 300, 400, g_hWnd, NULL, hInst, NULL);
   m_SFMLView.Create(m_SFMLWindow);

   if (!g_hWnd)
   {
      return FALSE;
   }

   ShowWindow(g_hWnd, nCmdShow);
   UpdateWindow(g_hWnd);

   m_SFMLView.Show(true);

   return TRUE;
}

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE:  Processes messages for the main window.
//
//  WM_COMMAND - process the application menu
//  WM_PAINT - Paint the main window
//  WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;

switch (message)
{
case WM_COMMAND:
wmId    = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
//DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
/*case WM_PAINT:
m_SFMLView.Clear();

TestScene.Draw(&m_SFMLView);

m_SFMLView.Display();
break;*/
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;

case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}


UIScene.cpp contains my rendering logic:

Code: [Select]
#include "stdafx.h"
#include "UIScene.h"
#include "Helpers.h"

namespace UI
{
string Crunch(string Str);

UIScene::UIScene(std::string ScriptPath)
{
ifstream UIScript(ScriptPath.c_str());

if(UIScript.is_open())
{
string CurrentLine;
vector<string> Params;
vector<UIProperty> Properties; //Shared properties for controls defined in a block.

cout << "Loaded UIScript: " << ScriptPath << "\r\n";

while(getline(UIScript, CurrentLine))
{
//Trim all leading and trailing spaces from a statement.
Helpers::Trim(CurrentLine);
CurrentLine = Crunch(CurrentLine);

if(CurrentLine != "")
{
Helpers::StringSplit(CurrentLine, " ", &Params);

//# == comment.
if(CurrentLine.substr(0, 1) != "#")
{
if(Params.size() > 1)
{
if(Params[0] == "DefineImage")
{
UIImage Img(Params[1], Params[3], ScriptPath);

m_Images.push_back(Img);

//TODO: Load imagedata from ID...
}
else if(Params[0] == "Begin" && Params[2] == "stringDir")
{
cout << "Found StringTable header!" << "\r\n";
//The SetSharedProperty 'function' for stringtables also includes a directory
//parameter, but all the text in the game is in the uitext directory anyways...
int TableID = atoi(Params[5].c_str());
m_StrTable = StringTable(TableID);
}
//The previous section that defines 'access' to the stringtable itself
//will always come before the strings, so it's safe to assume the table
//has been loaded at this point.
else if(Params[0] == "DefineString")
{
int StrID = atoi(Params[3].c_str());
//cout << "ID: " << StrID << "\r\n";

if(m_StrTable.GetStrFromID(StrID))
{
m_StrTable.GetStrFromID(StrID)->SetLabel(Params[1]);
//cout << "Label: " << Params[1] << "\r\n";
}
}
else if(Params[0] == "Begin" && Params[1] == "SetSharedProperties")
{
for(int i = (Params.size() - 1); i > 2; i = i - 2)
{
UIProperty Prop(Params[i - 1], Params[i]);
Properties.push_back(Prop);
}
}
else if(Params[0] == "End")
{
Properties.clear();
}
else if(Params[0] == "AddButton")
{
//Position looks like: 123,456
vector<string> XY;
Helpers::StringSplit(Params[5], ",", &XY);

UIButton Btn(Params[1], atoi(Params[3].c_str()),
atoi(XY[0].c_str()), atoi(XY[1].c_str()), &m_Images);

for(unsigned int i = 0; i < Properties.size(); i++)
{
Btn.AddProperty(Properties[i], &m_StrTable);
//cout << "Added property!" << "\r\n";
}

m_UIElements.push_back(Btn);
}
else if(Params[0] == "AddSlider")
{
vector<string> XY;
Helpers::StringSplit(Params[5], ",", &XY);

UISlider Slider(Params[1], atoi(Params[3].c_str()),
atoi(XY[0].c_str()), atoi(XY[1].c_str()), &m_Images);

for(unsigned int i = 0; i < Properties.size(); i++)
Slider.AddProperty(Properties[i], &m_StrTable);

m_UIElements.push_back(Slider);
}
}
}
}

Params.clear();
}
}

UIScript.close();
}

//Removes all extraneous tabs and spaces from within a string,
//in addition to removing all unneccessary and redundant characters
//from a string (<,>,=,").
string Crunch(string Str)
{
Helpers::Replace(Str, "(", " ");
Helpers::Replace(Str, ")", " ");
//Helpers::Replace(Str, ",", " ");
Helpers::Replace(Str, "<", " ");
Helpers::Replace(Str, ">", " ");
Helpers::Replace(Str, "=", " ");
Helpers::Replace(Str, "\"", " ");

stringstream StrStream(Str);
string Word;
string NewLine = "";

while(StrStream >> Word)
NewLine = NewLine + Word + " ";

return NewLine;
}

UIImage *UIScene::GetUIImage(std::string ImgLabel)
{
for(unsigned int i = 0; i < m_Images.size(); i++)
{
if(m_Images[i].GetLabel() == ImgLabel)
return &m_Images[i];
}
}

void UIScene::Draw(sf::RenderWindow *Wnd)
{
sf::Sprite Spr;

for(unsigned int i = m_UIElements.size(); i > 0; i--)
m_UIElements[i].Draw(Wnd);
}
}


UIButton.cpp derives from class UIElement and shows how I Draw() a Sprite.

Code: [Select]
#include "stdafx.h"
#include "UIButton.h"
#include "Helpers.h"

UIButton::UIButton(string Label, int ID, int X, int Y, vector<UIImage> *ImgList)
{
m_Label = Label;
m_ID = ID;
m_X = X;
m_Y = Y;
m_ImgList = ImgList;
}

void UIButton::Draw(sf::RenderWindow *Wnd)
{
sf::Sprite Spr;
Spr.SetImage(*(m_Img->GetImage()));
Spr.SetX(m_X);
Spr.SetY(m_Y);
Spr.SetBlendMode(sf::Blend::Mode::Alpha);

Wnd->Draw(Spr);
}

void UIButton::AddProperty(UIProperty Property, StringTable *StrTable)
{
if(Property.GetName() == "image")
{
for(unsigned int i = 0; i < (*m_ImgList).size(); i++)
{
if((*m_ImgList)[i].GetLabel() == Property.GetValue())
m_Img = &(*m_ImgList)[i];
}
}
else if(Property.GetName() == "tracking")
m_Tracking = atoi(Property.GetValue().c_str());
else if(Property.GetName() == "trigger")
m_Trigger = atoi(Property.GetValue().c_str());
else if(Property.GetName() == "tooltip")
m_ToolTip = *StrTable->GetStrFromLabel(Property.GetValue());
else if(Property.GetName() == "size")
{
vector<string> SplitString;
Helpers::StringSplit(Property.GetValue(), ",", &SplitString);

m_Width = atoi(SplitString[0].c_str());
m_Height = atoi(SplitString[1].c_str());
}
}


Any idea what's wrong?

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Sprites not showing up?
« Reply #1 on: January 19, 2011, 05:07:40 pm »
This is far too much code with a lot of unrelated details. Reduce it to a minimal and complete example that still shows your problem.
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

MatsVed

  • Newbie
  • *
  • Posts: 7
    • MSN Messenger - afr088@hotmail.com
    • View Profile
Sprites not showing up?
« Reply #2 on: January 19, 2011, 05:15:08 pm »
My problem is that none of my sprites are showing up!

I shortened down the main *.cpp file by removing all references to DirectX (that had previously been commented out).

Here is how I load an image:

Code: [Select]
#include "stdafx.h"
#include "UIImage.h"
#include "libfar.h"

UIImage::UIImage(string Label, string HexAssetID, string ScriptPath)
{
m_Label = Label;
m_HexAssetID = HexAssetID.substr(0, 10);

/*string Archive = "personselection.dat";
unsigned char *Destination;

unsigned int NumBytes = ExtractItemFromFARByID((char *)Archive.c_str(), (unsigned long)0x000007C, &Destination, 0);

if(NumBytes > 0)
cout << "Extraction was successful!\r\n";*/
vector<string> SplitResult;

//Split, in order to get the name of the folder of the archive.
Helpers::StringSplit(ScriptPath, "\\", &SplitResult);
//This assumes ScriptPath equals 'gamedata\\uiscripts\\nameofscript.uis'.
string ArchiveFolder = "uigraphics\\" + SplitResult[2] + "\\";
Helpers::Replace(ArchiveFolder, ".uis", "");

//Image didn't exist in current folder...
if(!m_Image.LoadFromFile(ArchiveFolder + m_HexAssetID))
{
//... meaning it was a Gizmo!
m_Image.LoadFromFile("uigraphics\\gizmo\\" + m_HexAssetID);
}
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Sprites not showing up?
« Reply #3 on: January 19, 2011, 05:17:39 pm »
Keep in mind that sprites keep a pointer to images. So if they move in memory, the pointer may become invalid, and your sprite won't be able to display anything else than plain white.

Now the link with your code: you're storing images in a vector, which moves elements in memory when it needs to grow, invalidating all sprites that were already pointing to images in the vector.

(sorry if I'm wrong, I didn't read all your code)
Laurent Gomila - SFML developer

MatsVed

  • Newbie
  • *
  • Posts: 7
    • MSN Messenger - afr088@hotmail.com
    • View Profile
Sprites not showing up?
« Reply #4 on: January 19, 2011, 08:04:00 pm »
I don't think this is the problem though.
Cos no sprites are created before the images are loaded.
I.E I'm not extending the vector by an elements after a sprite has been created.

MatsVed

  • Newbie
  • *
  • Posts: 7
    • MSN Messenger - afr088@hotmail.com
    • View Profile
Sprites not showing up?
« Reply #5 on: January 19, 2011, 08:16:45 pm »
Order of execution

UIScene instance is instantiated. The constructor parses a UI script.

As the script is parsed, UIImage instances are created and added to a vector in the UIScene. As are UIButtons and UISliders.

Each UIButton and UISlider has a pointer to the UIImage used to represent it on the screen. When UIElement.Draw() is called, a Sprite instance is created and used to draw the sf::Image instance within UIImage.

MatsVed

  • Newbie
  • *
  • Posts: 7
    • MSN Messenger - afr088@hotmail.com
    • View Profile
Sprites not showing up?
« Reply #6 on: January 19, 2011, 08:38:08 pm »
Ok, I moved my code changes over to my Console application that I've used for debug purposes.
It turns out that the reason it isn't displaying anything is because it is saying 'BMP type not supported: RLE'.
Does that mean I have to convert all my graphics? :(

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Sprites not showing up?
« Reply #7 on: January 19, 2011, 08:41:00 pm »
Quote
It turns out that the reason it isn't displaying anything is because it is saying 'BMP type not supported: RLE'.

Does this mean that you never check the return value of LoadFromFile?? :shock:

Quote
Does that mean I have to convert all my graphics?

Yes, and it's not a bad idea anyway, BMP is really a bad choice, even with RLE. PNG will be at least as good, with support for alpha in bonus.
Laurent Gomila - SFML developer

korath

  • Newbie
  • *
  • Posts: 2
    • View Profile
Sprites not showing up?
« Reply #8 on: February 03, 2011, 04:30:11 pm »
I'm having much the same problem and if I'm following you right, its the vector container thats causing it. If this is what your saying, do you have a recommendation on how to fix it or a vector alternative?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Sprites not showing up?
« Reply #9 on: February 03, 2011, 04:37:39 pm »
There are many solutions:
- use std::list, because elements stored in a list never move in memory
- use std::vector<sf::Image*>, the pointers will move in memory but no the image instances
- otherwise, call SetImage on all sprites after the vector is completely filled
Laurent Gomila - SFML developer

korath

  • Newbie
  • *
  • Posts: 2
    • View Profile
Sprites not showing up?
« Reply #10 on: February 03, 2011, 05:35:56 pm »
I appreciate the fast response, the vector of pointers fixed my problems, thanks