View Full Version : [C++] Varie richieste: Registro,grafica e gamescrolling
xeeynamo
17-02-2009, 21:50
Ciao a tutti ^^
Allora, stò creando delle piccole librerie, solo che ho un problema nell'uso del registro, e sia sull'msdn sia in giro su internet non ho trovato un granchè :(.. Mi manca il supporto alla lettura delle DWORD nel registro, solo che stranamente non riesco ad ottenere il valore vero della DWORD (Al contrario delle stringhe, che le ottengo con successo). Avrei pure bisogno di una mano su come rinominare o cancellare le varie chiavi, stringhe o dword nel registro (anche se credo di pretendere troppo :muro: ). (Se siete interessati nell'usare queste librerie, non esitate a chiedere :D)
Le altre due cose sono solo curiosità:
Mi piacerebbe gestire al pieno, grafica bidimensionale.. Credo che però l'unico modo è gestirla a basso livello. Sono a conoscienza di alcune librerie tipo le famose DirectX e OpenGL, ma che ormai gestiscono il 2D solo via emulazione, oppure le SDL, che però non mi piacciono per niente:mad: ! Magari con una gestione manuale di ogni singolo pixel sulla finestra, gestione di palette, sprites ecc... Ci sono un sacco di giochi vecchi che sfruttano questi sistemi, quindi non dovrebbe essere assai complesso ed elaborioso (o almeno prima di aver creato l'intero engine).
Infine l'ultima cosa che purtroppo non ho mai capito... I giochi tipo supermario, quando la telecamera si sposta, si sposta solo il personaggio muovendo la telecamera (E come capperi si fa???:mc: ) oppure è l'intero livello (quindi background,tiles e oggetti) che viene spostato?
Scusate per le troppe domande >.< e spero di ricevere risposte chiare :)
Rispondo all'ultima. Si sposta lo sfondo. Si chiama two (o four) way scrolling. In pratica finchè lo sprite del giocatore si trova tra l'inizio della mappa e il centro dello schermo il movimento è applicato allo sprite.
Quando lo sprite arriva a metà se continua a camminare verso destra anzichè applicare il movimento allo sprite applichi un movimento contrario alla mappa.
Cioè l'omino resta fermo e la mappa gli scorre sotto i piedi.
E' molto semplice da realizzare perchè in pratica si traduce in un valore "offset" che determina il punto a partire dal quale iniziare a disegnare sullo schermo le immagini che compongono la mappa.
Se il giocatore si trova sulla linea (X = metà della larghezza dello schermo) successivi incrementi della sua posizione verso X+ sono tradotti in una diminuzione dell'offset della mappa di valore pari all'incremento.
Lo scorrimento verso X positivo termina quando il giocatore si trova in una posizione tale che la sua ordinata più metà della larghezza dello schermo più il modulo dell'offset corrispondono alla larghezza totale della mappa. (credo, l'ho detta un po' di volata ma dovrebbe essere questa).
La parte che resta (cioè lo scorrimento verso X negativo e nelle due direzioni sull'asse Y) è la stessa minestra ricucinata.
per quanto riguarda il registro di sistema, incolla un po' di codice che non ti funziona e vediamo gli errori; se possibile riporta anche il codice numerico degli errori.
se possono esserti utili ti incollo qui un paio di classi che mi sono fatto qualche giorno fa per accedere al registro di sistema, solo che ancora non ho avuto mai occasione di testarle quindi non ho idea se funzionino o meno.
file RegKey.h:
#pragma once
class CRegKey;
class CRegValue
{
private:
HKEY m_hKey;
const tstring m_strName;
public:
CRegValue(HKEY a_hKey, LPCTSTR pszName);
operator DWORD () const;
operator tstring () const;
DWORD operator = (DWORD dwValue);
LPCTSTR operator = (LPCTSTR pszValue);
VOID Erase();
};
class CRegKey
{
private:
HKEY m_hKey;
inline CRegKey(CRegKey&) {}
inline VOID operator = (CRegKey&) {}
public:
CRegKey(HKEY hkParent, LPCTSTR pszPath);
virtual ~CRegKey();
CRegValue operator [] (LPCTSTR pszValueName);
const CRegValue operator [] (LPCTSTR pszValueName) const;
};
file RegKey.cpp:
#include "stdafx.h"
#include "RegKey.h"
#include "Error.h"
CRegValue::CRegValue(HKEY a_hKey, LPCTSTR pszName) :
m_hKey(a_hKey),
m_strName(pszName)
{
}
CRegValue::operator DWORD () const
{
DWORD dwValue;
DWORD cbValue = sizeof(DWORD);
LONG lResult = ::RegQueryValueEx(m_hKey, m_strName.c_str(), NULL, NULL, (LPBYTE)&dwValue, &cbValue);
::CheckResult(lResult);
return dwValue;
}
CRegValue::operator tstring () const
{
DWORD cbData = 0;
LONG lResult = ::RegQueryValueEx(m_hKey, m_strName.c_str(), NULL, NULL, NULL, &cbData);
::CheckResult(lResult);
DWORD cchData = cbData / sizeof(TCHAR);
LPTSTR pszData = new TCHAR[cchData + 1];
lResult = ::RegQueryValueEx(m_hKey, m_strName.c_str(), NULL, NULL, (LPBYTE)pszData, &cbData);
if (lResult != ERROR_SUCCESS)
{
delete pszData;
::RaiseError(lResult);
}
else
{
pszData[cchData] = 0;
tstring strData = pszData;
delete pszData;
return strData;
}
}
DWORD CRegValue::operator = (DWORD dwValue)
{
LONG lResult = ::RegSetValueEx(m_hKey, m_strName.c_str(), 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
::CheckResult(lResult);
return dwValue;
}
LPCTSTR CRegValue::operator = (LPCTSTR pszValue)
{
DWORD cbValue = (::lstrlen(pszValue) + 1) * sizeof(TCHAR);
LONG lResult = ::RegSetValueEx(m_hKey, m_strName.c_str(), 0, REG_SZ, (LPBYTE)pszValue, cbValue);
::CheckResult(lResult);
return pszValue;
}
VOID CRegValue::Erase()
{
LONG lResult = ::RegDeleteValue(m_hKey, m_strName.c_str());
::CheckResult(lResult);
}
CRegKey::CRegKey(HKEY hkParent, LPCTSTR pszPath)
{
LONG lResult = ::RegCreateKeyEx(hkParent, pszPath, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &m_hKey, NULL);
::CheckResult(lResult);
}
CRegKey::~CRegKey()
{
LONG lResult = ::RegCloseKey(m_hKey);
::CheckResult(lResult);
}
CRegValue CRegKey::operator [] (LPCTSTR pszValueName)
{
return CRegValue(m_hKey, pszValueName);
}
const CRegValue CRegKey::operator [] (LPCTSTR pszValueName) const
{
return CRegValue(m_hKey, pszValueName);
}
file Error.h:
#pragma once
__declspec(noreturn) VOID RaiseError(DWORD dwErrorCode);
__declspec(noreturn) VOID RaiseLastError();
__declspec(noreturn) VOID RaiseErrorFromHResult(HRESULT hr);
inline VOID CheckResult(DWORD dw)
{
if (dw != ERROR_SUCCESS)
{
RaiseError(dw);
}
}
inline VOID CheckHResult(HRESULT hr)
{
if (FAILED(hr))
{
RaiseErrorFromHResult(hr);
}
}
file Error.cpp:
#include "stdafx.h"
#include "Error.h"
VOID RaiseError(DWORD dwErrorCode)
{
RaiseException(dwErrorCode, EXCEPTION_NONCONTINUABLE, 0, NULL);
}
VOID RaiseLastError()
{
RaiseError(GetLastError());
}
VOID RaiseErrorFromHResult(HRESULT hr)
{
RaiseError(HRESULT_CODE(hr));
}
file stdafx.h:
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <unknwn.h>
#include <cassert>
#include <string>
using namespace std;
#ifdef UNICODE
#define tstring wstring
#else
#define tstring string
#endif
occhio, sono progettate per lanciare eccezioni SEH in caso di errore; significa che se non catturi le eccezioni mandano in crash il processo (é una caratteristica voluta, mi permette di ottenere un dump comprensivo di codice di errore quando qualcosa non funziona nel mio programma, cosi da poterlo debuggare anche se il malfunzionamento é avvenuto su un'altra macchina).
xeeynamo
18-02-2009, 14:35
#include <stdio.h>
#include <windows.h>
DWORD *RegGet(HKEY hKey,const char *path,const char *name){
HKEY hk;
DWORD dwType=REG_DWORD;
DWORD dwSize=255;
DWORD Return[255];
RegOpenKeyEx(hKey,(char*)path,0,KEY_ALL_ACCESS,&hk);
RegQueryValueEx(hk,name, NULL, &dwType,(BYTE*)&Return, &dwSize);
return Return;
}
int main(){
printf("%X",RegGet(HKEY_LOCAL_MACHINE,"SOFTWARE\\MICROSOFT\\WINDOWS NT\\CURRENTVERSION","InstallDate"));
}
L'output è sempre 22FB00, qualunque valore abbia la DWORD. Scusa per gli errori o per il codice un pò fatto "a casaccio" ma sono un principiante della programmazione, e sò poco sulla gestione delle classi :cry:
Rispondo all'ultima. Si sposta lo sfondo. Si chiama two (o four) way scrolling. In pratica finchè lo sprite del giocatore si trova tra l'inizio della mappa e il centro dello schermo il movimento è applicato allo sprite.
Quando lo sprite arriva a metà se continua a camminare verso destra anzichè applicare il movimento allo sprite applichi un movimento contrario alla mappa.
Cioè l'omino resta fermo e la mappa gli scorre sotto i piedi.
E' molto semplice da realizzare perchè in pratica si traduce in un valore "offset" che determina il punto a partire dal quale iniziare a disegnare sullo schermo le immagini che compongono la mappa.
Se il giocatore si trova sulla linea (X = metà della larghezza dello schermo) successivi incrementi della sua posizione verso X+ sono tradotti in una diminuzione dell'offset della mappa di valore pari all'incremento.
Lo scorrimento verso X positivo termina quando il giocatore si trova in una posizione tale che la sua ordinata più metà della larghezza dello schermo più il modulo dell'offset corrispondono alla larghezza totale della mappa. (credo, l'ho detta un po' di volata ma dovrebbe essere questa).
La parte che resta (cioè lo scorrimento verso X negativo e nelle due direzioni sull'asse Y) è la stessa minestra ricucinata.
Allora era come immaginavo.. Quindi ad esempio ho un giochetto con risoluzione 640x480 e il pg si trova a coordinate (0,240). Quando lo faccio spostare, lui si muove sino alle coordinate (320,240) e da quel momento in poi, quando lo muovo avanti tutta la mappa si sposta facendo in modo che il pg si trovi sempre al centro.. Lo sfondo e la mappa è facile da spostare :D ma se ho ad esempio ostacoli mobili? Dovrei gestire sia il suo movimento, sia la sua posizione nella mappa contemporaneamente giusto? Per fare questo ovviamente dovrei andare però a interagire con il thread che gestisce l'ostacolo, ma come ?_?... Oddio la facevo più facile la programmazione di giochi 2D a scrolling XD, significa che dovrò mettermi d'impegno!
xeeynamo, il codice che hai riportato commette atti osceni: i piu evidenti, ma non gli unici, sono il fatto che ritorni l'indirizzo di un buffer locale (che viene deallocato non appena esci dalla funzione), il fatto che non controlli i valori di ritorno ed il fatto che non chiudi gli handles che apri.
poi non capisco perché hai allocato 255 DWORD anziché uno visto che te ne bastava uno solo; ed infine non capisco come mai 255 e non 256 :D
ti riscrivo il codice con qualche correzione fondamentale, ma non l'ho testato e quindi non so se ci sono altri errori.
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
DWORD RegGet(HKEY hKey, LPCTSTR path, LPCTSTR name){
HKEY hk;
DWORD dwSize=sizeof(DWORD);
DWORD Return;
RegOpenKeyEx(hKey, path, 0, KEY_ALL_ACCESS, &hk);
RegQueryValueEx(hk, name, NULL, NULL, (BYTE*)&Return, &dwSize);
RegCloseKey(hk);
return Return;
}
int main(){
printf("%X", RegGet(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\MICROSOFT\\WINDOWS NT\\CURRENTVERSION"), _T("InstallDate")));
return 0;
}
per il futuro leggi piu attentamente la documentazione in MSDN, ti avrebbe chiarito tutto.
xeeynamo
18-02-2009, 19:14
xeeynamo, il codice che hai riportato commette atti osceni: i piu evidenti, ma non gli unici, sono il fatto che ritorni l'indirizzo di un buffer locale (che viene deallocato non appena esci dalla funzione), il fatto che non controlli i valori di ritorno ed il fatto che non chiudi gli handles che apri.
poi non capisco perché hai allocato 255 DWORD anziché uno visto che te ne bastava uno solo; ed infine non capisco come mai 255 e non 256 :D
ti riscrivo il codice con qualche correzione fondamentale, ma non l'ho testato e quindi non so se ci sono altri errori.
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
DWORD RegGet(HKEY hKey, LPCTSTR path, LPCTSTR name){
HKEY hk;
DWORD dwSize=sizeof(DWORD);
DWORD Return;
RegOpenKeyEx(hKey, path, 0, KEY_ALL_ACCESS, &hk);
RegQueryValueEx(hk, name, NULL, NULL, (BYTE*)&Return, &dwSize);
RegCloseKey(hk);
return Return;
}
int main(){
printf("%X", RegGet(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\MICROSOFT\\WINDOWS NT\\CURRENTVERSION"), _T("InstallDate")));
return 0;
}
per il futuro leggi piu attentamente la documentazione in MSDN, ti avrebbe chiarito tutto.
Oddio, scandaloso:eek: DEVO imparare a programmare!!! Grazie per i consigli e grazie per il codice che risulta funzionare alla perfezione:D spero proprio di raggiungere livelli alti!
Aspetto le altre risposte per le altre domande e poi il topic può essere tranquillamente chiuso :)
ma se ho ad esempio ostacoli mobili? Dovrei gestire sia il suo movimento, sia la sua posizione nella mappa contemporaneamente giusto? Per fare questo ovviamente dovrei andare però a interagire con il thread che gestisce l'ostacolo, ma come ?_?... Oddio la facevo più facile la programmazione di giochi 2D a scrolling XD, significa che dovrò mettermi d'impegno!
Qui viene il bello. Il movimento degli sprite in una mappa a scorrimento è indipendente dallo scorrimento perchè si svolge nello spazio di coordinate della mappa e non dello schermo.
E' solo quando disegni che tieni conto dello scorrimento. Quando dico "la posizione è aggiornata" intendo "visivamete". Logicamente le coordinate degli sprite si svolgono sull'intero piano di gioco.
Vale a dire che se la mia mappa è di 10.000x10.000 pixel i miei sprite possono avere come posizione una qualsiasi coppia di valori x,y compresi tra 0 e 10.000.
E' nel ciclo di rendering che si applicano le trasformazioni. La posizione del giocatore su uno schermo da 640x480 con scorrimento (sx, sy) è:
x - sx + 320 SE x > 320
y - sy + 240 SE y > 240
Nella parte logica del motore di gioco la posizione degli sprite viene sempre aggiornata e contemporaneamente aggiorno lo scorrimento se se ne verifichino le condizioni.
Vale a dire che se la mia mappa è di 10.000x10.000 pixel i miei sprite possono avere come posizione una qualsiasi coppia di valori x,y compresi tra 0 e 10.000. 9.999
banryu79
19-02-2009, 14:14
Ach, imperdonabile! :D
Per dirla alla Mike Bongiorno:
Ahi, ahi ahi, signor PGI, lei mi è caduto sul.... l'indice :D
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.