Making a quiz game.

Started by madradubhcroga, Tue 15/05/2012 10:18:54

Previous topic - Next topic

madradubhcroga


Hi everybody.

I'm getting the hang of AGS, and I like it very much.
But I'm going to put my Adventure Game project on hold:
I want to make a 'quiz' game using AGS.

I think it'll be good, with trivia categories, reflex based games, puzzles, picture, memory, and audio challenges.

But there are distinct technical issues.


The big one is making databases to hold categories of questions, and difficulty levels of those questions.

I'd like to represent the category selection as a big spinning 'wheel of fortune' so not quite random but rather the wheel slows to a stop on a category (eg 'Animals').  Then Animals appears on the Question Map(GUI), with  10 20 30 40 and 50 point buttons (randomly from the relevent databases).  They spin the wheel again and so on until the Question Map(GUI) looks like this:



animals music mystery literature
10       10     10      10         10
20       20     20      20         20
30       30     30      30         30


Like in 'Jeopardy'
I want the player(s) to be able to select a question (EG Animals, for 30 points).  Then the computer should select an Animals question randomly from the correct database of 30 point animal questions.

I think I can just about make that happen.  But does anybody know the best way to proceed?  I don't see how to make it easy to go back and upload more questions when the structure is in place. Assuming I get that far. without haduken-ing my monitor.

I don't mean to make someone else do all the work for me;
but collaborators opinions and colossal insights are all alike welcome.


Monsieur OUXX

#1
First, I don't think this should be in "Advanced technical forum" because even though it's technical, the difficulty comes from the algorithms rather than AGS itself. the AGS points you raise are rather simple.

You ask quite many questions:

1) How do I display my spinning wheel?

- There is a plugin that allows you to rotate sprites and draw them into a dynamicSprite. I can't remember the exact name but it has "3D" in it and it's still within the first 2 pages of the "Modules and plugins" forum.
- Alternative solution: Create a short animation or video of a spinning wheel.

2) How do I load questions from a database?

Well, it's not too hard to have one file per duet "[category]x[number of points]". For example, "Animals_30points.txt". Then you just read the question and its answer from the file.
The difficulty is: How big are the files? Can you afford to perform a random-access in the file every time ? (which means you have to re-read a lot of it everytime, which can stall your game if the file is huge). Should you load the file contents into memory? Should you devise a clever "partition" system to split the file into smaller files? Etc. that's all up to you.

3) How to I display more and more buttons in columns and rows?

Well, just create a GUI with 40 buttons and then make them invisible. Show them only when needed.
If you hit the limit of buttons per GUI (I believ a GUI cannot have more than 20 controls) then use several GUIs.

 

Khris

I'd implement reading CSV files. That way you (or anybody else) can easily just type random questions into any spreadsheet app and save it as .csv.
As an example:



animals 10    This ape is known for flinging poo and eating babies.    Chimpanzee   
literature    20  The arch enemy of Sherlock Holmes is?  Dr. Moriarty

Exported as CSV, it'll look like this:
animals;10;This ape is known for flinging poo and eating babies.;Chimpanzee
literature;20;The arch enemy of Sherlock Holmes is?;Dr. Moriarty

At the start of the game, every CSV file in a set data dir is imported into a database (a struct array).

One could in addition specify which pack a csv belongs to, then add an option to only use certain question packs.

To parse a CSV file, read it line by line and split the lines at a , or ;
That's quite easily done using the File.Open() and File.ReadRawChar() commands.

Monsieur OUXX

Quote from: Khris on Tue 15/05/2012 14:08:45
I'd implement reading CSV files.

+1. Simplest structure ever: Just read each line in the file and then parse the line, looking for commas
 

madradubhcroga

Thank you for your consideration.

I understand that I may not have selected the appropriate forum, sorry for any inconvenience.

Khris- that CSV system sounds promising, I may try that eventually.  Maybe another way would be to implement your solution to my Re: Where is the 'Room message editor?' question.


I'm going to sketch out a plan and then I'll be able to ask more specific questions.

Best regards

MDC

MDC

Khris

#5
Ok, here's a module with basic support for importing a CSV database of questions with categories, points and four answers.

QuizModule.scm (Right-click the Scripts node and choose "Import script...")

Here's an example CSV file: misc.csv (Inside the Compiled folder, create a folder called "questions" and put it in there.)

And some example code you can put in a room script:
Code: ags
void on_key_press(eKeyCode k) {
  
  if (k == eKeySpace) {
    QuizModule.ImportQuestions("misc");
    int noq = QuizModule.NumberOfQuestions();
    
    Display(String.Format("Loaded %d questions.", noq));
    int i;
    String questions = "";
    while (i < noq) {
      questions = questions.Append(q[i].question);
      if (i < noq-1) questions = questions.Append("[---[");
      i++;
    }
    Display(questions);
  }
}


If you press space while in the room, this will import the file questions/misc.csv, show the number of successfully imported questions and then display the questions.
q is a global struct array holding all the questions data. I've decided that specifying the right answer isn't really necessary if you put it as first of the four possible answers in the database, then put them on four buttons in random order.

Btw, the module assumes that the CSV file uses ; as delimiter and doesn't have "s around text.

madradubhcroga

How do I put the answers on the buttons?

Khris

Create a GUI called gQuestion, add a label first, then four buttons to it, so the latter have the IDs 1-4.
Now append this to Quiz.asc:

Code: ags
int correct_id;
export correct_id;

static void QuizModule::SetupQuestionGUI(int question) {
  Label*l = gQuestion.Controls[0].AsLabel;
  l.Text = q[question].question;
  
  // positions 0-3
  int p[4];
  int i;
  while (i < 4) {
    p[i] = i;
    i++;
  }
  // shuffle
  i = 0;
  while (i < 20) {
    int a = Random(3);
    int b = Random(3);
    int sum = p[a] + p[b];
    p[a] = sum - p[a];
    p[b] = sum - p[b];
    i++;
  }
  // put answers on buttons
  i = 0;
  while (i < 4) {
    int id = i + 1;
    Button*b = gQuestion.Controls[id].AsButton;
    b.Text = q[question].ans[p[i]];
    // if we put the correct answer (ans[0]) on the button, store its id
    if (p[i] == 0) correct_id = id;
    i++;
  }
}


and add this to Quiz.ash:
Code: ags
import int correct_id;


(I have also updated the module download in my Dropbox.)

Now open GlobalScript.asc and add this at the end:
Code: ags
function QuizButton_OnClick(GUIControl*control, MouseButton button)
{
  if (button != eMouseLeft) return;
  if (control.ID == correct_id) Display("Correct!");
  else Display("False!");
}


Final step: open the event pane of each of the four buttons and put "QuizButton_OnClick" without quotes in the empty field next to "OnClick".

You can test this by calling  QuizModule.SetupQuestionGUI(0); after you've imported some questions.

madradubhcroga


Hi.

I havn't gotten it working yet.

I get an error  on line 114
Code: AGS


  l.Text = q[question].question;



the error is highlighted in yellow and the message reads

Null string supplied to CheckForTranslations




Khris

When you call QuizModule.SetupQuestionGUI(x);, make sure that you have already imported a CSV file and that x is smaller than the total number of questions.
Otherwise, q[question].question won't just be empty, it'll be null, and AGS doesn't seem to like assigning null to a Label's .Text property.

madradubhcroga

Legend. 
I'll try that, thank you.

FrankT

Couldn't help but notice this. I'm looking at a concept for a quiz too! If I ever get it done, I'll be sure to thank you for it!

madradubhcroga

I haven't successfully implemented the code yet, the same error is being reported.


I used Google spreadsheets to make test.csv and replaced the , with ;
Test.csv has 10 questions and is saved in Q3/Compiled/Questions.

(Q3 is a new game project, with nothing in it except the quiz script.)

the room script file looks like this:

Code: AGS


// room script file
    void on_key_press(eKeyCode k) {
     
      if (k == eKeySpace) {
        QuizModule.ImportQuestions("test");
        int noq = QuizModule.NumberOfQuestions();
       
        Display(String.Format("Loaded %d questions.", noq));
        int i;
        String questions = "";
        while (i < noq) {
          questions = questions.Append(q[i].question);
          if (i < noq-1) questions = questions.Append("[---[");
          i++;
        }
        Display(questions);
      }
    
   
   }
    
    

    
function room_FirstLoad()
{
QuizModule.SetupQuestionGUI(5);
}


 

Khris

Yeah, just like I said in my previous port, you can't call QuizModule.SetupQuestionGUI(5); until after you've imported the file.
The example code I posted containing the on_key_press funtion won't do anything until you press the space key. Thus, room_FirstLoad is executed first and throws the error.

Try this:
Code: ags
function room_FirstLoad()
{
  QuizModule.ImportQuestions("test");
  QuizModule.SetupQuestionGUI(5);
}

madradubhcroga

No joy. 
The same error message:

Null string supplied to CheckForTranslations

appears in relation to 
Code: AGS


 l.Text = q[question].question;


In the morning, I'll start again from the beginning.  Maybe I've strayed from the recipe somewhere.

Khris

#15
Alright, remove the QuizModule.SetupQuestionGUI(5); line.
Put the on_key_press code in a room and in-game, go to that room and press space.
The game should say how many questions were imported and then list them.

If that does work, you can try putting the line back in.

Edit: Judging by this post, the error occurs if you try to set a label's text to a null string. In other words, you're trying to put a question on a label but there aren't any questions loaded (yet). Either your code is still wrong, or the CSV doesn't have the right format.

madradubhcroga


Re: "Either your code is still wrong, or the CSV doesn't have the right format."
Both, I think.



In the configuration, without  the QuizModule.SetupQuestionGUI(5); line,
when I press space,

the message

'0 questions loaded'

appears.

When I change 'test' to 'misc' in both the on_key_press code and in the
function room_FirstLoad,
the message

'loaded 4 questions'
appears, followed by the message:


the arch enemy of Sherlock holmes is?
----
Which of these actually exist?
----
the arch enemy of Sherlock holmes is?
----
Which of these actually exist?
----


So:
a) Your sample questions file (misc) is accessable, but mine (test) is not.  (Both are .csv files saved in the Questions folder in the Compiled folder. I'm going to compare them more carefully now)
b) My GUI 'gQuestion'  is not being called.   

Khris

The questions appear twice because you have imported my csv twice.
To be clear, the on_key_press code was just for testing/demo purposes; you don't need it for the quiz stuff to work.

All you need is the import command, followed by the SetupQuestionsGUI command(s).

As for parsing the CSV file, I put zero error-checking in there. Could you upload your CSV somewhere so I can take a look at it?


Khris

I've taken a look at it and it seems fine, however it's UTF-8/unicode, whereas mine is an ASCII file. I suspect that's the reason why the import routine fails.
I tried converting it to ascii, which converted all the special characters to question marks, and it still didn't work. I'll look into it later and report back.

SMF spam blocked by CleanTalk