From c1dda8efd8ea7bb753577baef1f9e1405805f9c0 Mon Sep 17 00:00:00 2001 From: sam-astro <77079540+sam-astro@users.noreply.github.com> Date: Fri, 14 Jan 2022 23:21:44 -0500 Subject: [PATCH] Updated graphics, got pong physics working --- Slang/Main.cpp | 184 ++++++++++++++++++++++++++-------------------- Slang/anyops.h | 78 ++++++++++++++++++-- Slang/builtin.h | 100 +++++++++++++++---------- Slang/builtin.slg | 26 +++---- Slang/eval.cpp | 18 ++--- Slang/graphics.h | 32 ++++++-- Slang/script.slg | 106 ++++++++++++++++---------- Slang/strops.cpp | 27 ++++++- Slang/strops.h | 7 +- 9 files changed, 379 insertions(+), 199 deletions(-) diff --git a/Slang/Main.cpp b/Slang/Main.cpp index b3258a4..b5ed737 100644 --- a/Slang/Main.cpp +++ b/Slang/Main.cpp @@ -25,12 +25,12 @@ unordered_map>> functionValues; boost::any GetVariableValue(const string& varName, const unordered_map& variableValues) { string classSubComponent; - string baseName = varName; + string baseName = trim(varName); if (count(varName, '.') > 0) { - classSubComponent = varName.substr(indexInStr(varName, '.')+1, -1); - baseName = split(varName, '.')[0]; + classSubComponent = trim(varName.substr(indexInStr(varName, '.') + 1, -1)); + baseName = trim(split(varName, '.')[0]); } boost::any outputValue = nullType; @@ -52,7 +52,7 @@ boost::any GetVariableValue(const string& varName, const unordered_map& variableValues) { - if (variableValues.find(split(varName, '.')[0]) != variableValues.end() && split(varName, '.')[0] != "CPP") + if (variableValues.find(split(varName, '.')[0]) != variableValues.end() && split(varName, '.')[0] != "SLB") return true; else return false; @@ -66,8 +66,8 @@ vector VarValues(const vector& varNames, unordered_mapsecond); @@ -78,8 +78,9 @@ vector VarValues(const vector& varNames, unordered_mapsecond); else - realValues.push_back(varName); - }*/ + realValues.push_back(EvalExpression(varName, variableValues)); + } + //InterpreterLog(varName + " " + AnyAsString(realValues[realValues.size() - 1])); } return realValues; @@ -92,9 +93,9 @@ bool IsFunction(const string& funcName) else return false; } -bool IsCPPFunction(const string& funcName) +bool IsSLBFunction(const string& funcName) { - if (funcName[0] == 'C' && funcName[1] == 'P' && funcName[2] == 'P' && funcName[2] == '.') + if (funcName[0] == 'S' && funcName[1] == 'L' && funcName[2] == 'B' && funcName[2] == '.') return true; else return false; @@ -105,10 +106,12 @@ boost::any EvalExpression(const string& ex, unordered_map& v string expression = trim(ex); bool inQuotes = false; - //InterpreterLog("OLDEXPRESSION: |" + expression + "|"); + InterpreterLog("OLDEXPRESSION: |" + expression + "|"); + bool isFunc = IsFunction(split(expression, '(')[0]); + bool isSLB = split(expression, '.')[0] == "SLB"; // If no operations are applied, then return self - if ((count(expression, '+') == 0 && count(expression, '-') == 0 && count(expression, '*') == 0 && count(expression, '/') == 0 && count(expression, '^') == 0) || split(expression, '.')[0] == "CPP") + if ((countOutsideParenthesis(expression, '+') == 0 && countOutsideParenthesis(expression, '-') == 0 && countOutsideParenthesis(expression, '*') == 0 && countOutsideParenthesis(expression, '/') == 0 && countOutsideParenthesis(expression, '^') == 0) || split(expression, '.')[0] == "SLB") { bool isFunc = IsFunction(split(expression, '(')[0]); if (isFunc && !inQuotes) @@ -122,10 +125,9 @@ boost::any EvalExpression(const string& ex, unordered_map& v y++; } - //InterpreterLog(split(expression, '(')[0] + " " + AnyAsString(GetVariableValue(split(argContents, ',')[0], variableValues))); return ExecuteFunction(split(expression, '(')[0], VarValues(split(argContents, ','), variableValues)); } - else if (split(expression, '.')[0] == "CPP" && !inQuotes) + else if (split(expression, '.')[0] == "SLB" && !inQuotes) { string argContents = ""; int y = indexInStr(expression, '(') + 1; @@ -135,8 +137,7 @@ boost::any EvalExpression(const string& ex, unordered_map& v y++; } - //InterpreterLog(split(expression, '(')[0] + " " + argContents); - return CPPFunction(split(expression, '(')[0], VarValues(split(argContents, ','), variableValues)); + return SLBFunction(split(expression, '(')[0], VarValues(split(argContents, ','), variableValues)); } else return GetVariableValue(expression, variableValues); @@ -177,7 +178,7 @@ boost::any EvalExpression(const string& ex, unordered_map& v newExpression += returnVal; //cout << newExpression << endl; } - else if (split(name, '.')[0] == "CPP" && !inQuotes) + else if (split(name, '.')[0] == "SLB" && !inQuotes) { string argContents = ""; int y = indexInStr(expression, '(') + 1; @@ -188,7 +189,7 @@ boost::any EvalExpression(const string& ex, unordered_map& v y++; } //cout << split(expression, '(')[0] << " " << argContents << endl; - string returnVal = AnyAsString(CPPFunction(split(name, '(')[0], VarValues(split(argContents, ','), variableValues))); + string returnVal = AnyAsString(SLBFunction(split(name, '(')[0], VarValues(split(argContents, ','), variableValues))); newExpression += returnVal; } else @@ -206,7 +207,7 @@ boost::any EvalExpression(const string& ex, unordered_map& v newExpression += expression[i]; } } - //InterpreterLog("NEW EXPRESSION: |" + newExpression + "|"); + InterpreterLog("NEW EXPRESSION: |" + newExpression + "|"); bool addStrings = false; for (int i = 0; i < (int)newExpression.size(); i++) @@ -243,11 +244,11 @@ bool BooleanLogic(const string& valA, const string& determinant, const string& v { boost::any valARealValue = EvalExpression(valA, variableValues); boost::any valBRealValue = EvalExpression(valB, variableValues); - //InterpreterLog(AnyAsString(valARealValue) + " " + determinant + " " + AnyAsString(valBRealValue) + " : " + to_string(AnyAsString(valARealValue) == AnyAsString(valBRealValue))); + //InterpreterLog(AnyAsString(valARealValue) + " " + determinant + " " + AnyAsString(valBRealValue) + " : " + AnyAsString(valA) + " " + determinant + " " + AnyAsString(valB) + " : " + to_string(AnyAsString(valARealValue) == AnyAsString(valBRealValue))); if (determinant == "==") - return AnyAsString(valARealValue) == AnyAsString(valBRealValue); + return any_compare(valARealValue, valBRealValue); else if (determinant == "!=") - return AnyAsString(valARealValue) != AnyAsString(valBRealValue); + return !any_compare(valARealValue, valBRealValue); else if (determinant == ">=") return AnyAsFloat(valARealValue) >= AnyAsFloat(valBRealValue); else if (determinant == "<=") @@ -264,63 +265,82 @@ bool BooleanLogic(const string& valA, const string& determinant, const string& v int varOperation(const vector& str, unordered_map& variableValues) { - try - { - if (count(str[0], '.') > 0) + if (IsVar(str[0], variableValues)) { - if (IsVar(split(str[0], '.')[0], variableValues)) + // Checks if type is simple, like int or string + if (any_type(variableValues[str[0]]) <= 3) { - //InterpreterLog(unWrapVec(vector(str.begin() + 2, str.end()))); - variableValues[split(str[0], '.')[0]] = EditClassSubComponent(variableValues[split(str[0], '.')[0]], str[1], EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues), split(str[0], '.')[1]); - return 0; + if (str[1] == "=") + variableValues[str[0]] = EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues); + else if (str[1] == "+=") + variableValues[str[0]] = EvalExpression(str[0] + "+(" + unWrapVec(vector(str.begin() + 2, str.end())) + ")", variableValues); + else if (str[1] == "-=") + variableValues[str[0]] = AnyAsFloat(variableValues[str[0]]) - AnyAsFloat(EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues)); + else if (str[1] == "*=") + variableValues[str[0]] = AnyAsFloat(variableValues[str[0]]) * AnyAsFloat(EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues)); + else if (str[1] == "/=") + variableValues[str[0]] = AnyAsFloat(variableValues[str[0]]) / AnyAsFloat(EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues)); + else + LogWarning("unrecognized operator \'" + str[1] + "\'"); } - else if (IsVar(split(str[0], '.')[0], globalVariableValues)) + // Else it is a Vec2. No other complex class can be operated on it's base form (ex. you can't do: Sprite += Sprite) + else if(any_type(variableValues[str[0]]) == 5) { - //InterpreterLog(unWrapVec(vector(str.begin() + 2, str.end()))); - globalVariableValues[split(str[0], '.')[0]] = EditClassSubComponent(globalVariableValues[split(str[0], '.')[0]], str[1], EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues), split(str[0], '.')[1]); - return 0; + boost::any otherExpression = EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues); + if (str[1] == "=") + variableValues[str[0]] = otherExpression; + else if (str[1] == "+=") + variableValues[str[0]] = AnyAsVec2(variableValues[str[0]]) + AnyAsVec2(otherExpression); + else if (str[1] == "-=") + variableValues[str[0]] = AnyAsVec2(variableValues[str[0]]) - AnyAsVec2(otherExpression); + else if (str[1] == "*=") + variableValues[str[0]] = AnyAsVec2(variableValues[str[0]]) * AnyAsFloat(otherExpression); + else if (str[1] == "/=") + variableValues[str[0]] = AnyAsVec2(variableValues[str[0]]) / AnyAsFloat(otherExpression); + else + LogWarning("unrecognized operator \'" + str[1] + "\'"); } - } - else if (IsVar(str[0], variableValues)) - { - if (str[1] == "=") - variableValues[str[0]] = EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues); - else if (str[1] == "+=") - variableValues[str[0]] = EvalExpression(str[0] + "+(" + unWrapVec(vector(str.begin() + 2, str.end())) + ")", variableValues); - else if (str[1] == "-=") - variableValues[str[0]] = AnyAsFloat(variableValues[str[0]]) - AnyAsFloat(EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues)); - else if (str[1] == "*=") - variableValues[str[0]] = AnyAsFloat(variableValues[str[0]]) * AnyAsFloat(EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues)); - else if (str[1] == "/=") - variableValues[str[0]] = AnyAsFloat(variableValues[str[0]]) / AnyAsFloat(EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues)); - else - LogWarning("unrecognized operator \'" + str[1] + "\'"); return 0; } else if (IsVar(str[0], globalVariableValues)) { - if (str[1] == "=") - globalVariableValues[str[0]] = EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues); - else if (str[1] == "+=") - globalVariableValues[str[0]] = EvalExpression(str[0] + "+(" + unWrapVec(vector(str.begin() + 2, str.end())) + ")", variableValues); - else if (str[1] == "-=") - globalVariableValues[str[0]] = AnyAsFloat(variableValues[str[0]]) - AnyAsFloat(EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues)); - else if (str[1] == "*=") - globalVariableValues[str[0]] = AnyAsFloat(variableValues[str[0]]) * AnyAsFloat(EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues)); - else if (str[1] == "/=") - globalVariableValues[str[0]] = AnyAsFloat(variableValues[str[0]]) / AnyAsFloat(EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues)); - else - LogWarning("unrecognized operator \'" + str[1] + "\'"); + // Checks if type is simple, like int or string + if (any_type(globalVariableValues[str[0]]) <= 3) + { + if (str[1] == "=") + globalVariableValues[str[0]] = EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues); + else if (str[1] == "+=") + globalVariableValues[str[0]] = EvalExpression(str[0] + "+(" + unWrapVec(vector(str.begin() + 2, str.end())) + ")", variableValues); + else if (str[1] == "-=") + globalVariableValues[str[0]] = AnyAsFloat(globalVariableValues[str[0]]) - AnyAsFloat(EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues)); + else if (str[1] == "*=") + globalVariableValues[str[0]] = AnyAsFloat(globalVariableValues[str[0]]) * AnyAsFloat(EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues)); + else if (str[1] == "/=") + globalVariableValues[str[0]] = AnyAsFloat(globalVariableValues[str[0]]) / AnyAsFloat(EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues)); + else + LogWarning("unrecognized operator \'" + str[1] + "\'"); + } + // Else it is a Vec2. No other complex class can be operated on it's base form (ex. you can't do: Sprite += Sprite) + else if (any_type(globalVariableValues[str[0]]) == 5) + { + boost::any otherExpression = EvalExpression(unWrapVec(vector(str.begin() + 2, str.end())), variableValues); + if (str[1] == "=") + globalVariableValues[str[0]] = otherExpression; + else if (str[1] == "+=") + globalVariableValues[str[0]] = AnyAsVec2(globalVariableValues[str[0]]) + AnyAsVec2(otherExpression); + else if (str[1] == "-=") + globalVariableValues[str[0]] = AnyAsVec2(globalVariableValues[str[0]]) - AnyAsVec2(otherExpression); + else if (str[1] == "*=") + globalVariableValues[str[0]] = AnyAsVec2(globalVariableValues[str[0]]) * AnyAsFloat(otherExpression); + else if (str[1] == "/=") + globalVariableValues[str[0]] = AnyAsVec2(globalVariableValues[str[0]]) / AnyAsFloat(otherExpression); + else + LogWarning("unrecognized operator \'" + str[1] + "\'"); + } return 0; } LogWarning("uninitialized variable or typo in \'" + str[0] + "\'"); return 1; - } - catch (const std::exception&) - { - LogWarning("uninitialized variable or typo in \'" + str[0] + "\'"); - return 1; - } } boost::any ProcessLine(const vector>& words, int lineNum, unordered_map& variableValues) @@ -331,10 +351,10 @@ boost::any ProcessLine(const vector>& words, int lineNum, unorder if (words[lineNum][0][0] == '/' && words[lineNum][0][1] == '/') return nullType; - // If print statement (deprecated, now use CPP.System.Print() function) + // If print statement (deprecated, now use SLB.System.Print() function) else if (words[lineNum][0] == "print") { - cout << AnyAsString(EvalExpression(unWrapVec(vector(words[lineNum].begin() + 1, words[lineNum].end())), variableValues)) << endl; + cout << StringRaw(AnyAsString(EvalExpression(unWrapVec(vector(words[lineNum].begin() + 1, words[lineNum].end())), variableValues))) << endl; return nullType; } @@ -342,14 +362,17 @@ boost::any ProcessLine(const vector>& words, int lineNum, unorder else if (words[lineNum][0] == "return") return EvalExpression(unWrapVec(vector(words[lineNum].begin() + 1, words[lineNum].end())), variableValues); - // Check if it is CPP Builtin function - else if (words[lineNum][0][0] == 'C' && words[lineNum][0][1] == 'P' && words[lineNum][0][2] == 'P' && words[lineNum][0][3] == '.') + // Check if it is SLB Builtin function + else if (words[lineNum][0][0] == 'S' && words[lineNum][0][1] == 'L' && words[lineNum][0][2] == 'B' && words[lineNum][0][3] == '.') return EvalExpression(unWrapVec(words[lineNum]), variableValues); // Check if it is function else if (IsFunction(trim(split(words[lineNum][0], '(')[0]))) { - ExecuteFunction(trim(split(words[lineNum][0], '(')[0]), VarValues(split(RMParenthesis(replace(unWrapVec(words[lineNum]), trim(split(words[lineNum][0], '(')[0]), "")), ','), variableValues)); + if(count(words[lineNum][0], '(') >0 && count(words[lineNum][0], ')') > 0) + ExecuteFunction(trim(split(words[lineNum][0], '(')[0]), vector()); + else + ExecuteFunction(trim(split(words[lineNum][0], '(')[0]), VarValues(split(RMParenthesis("(" + split(unWrapVec(rangeInVec(words[lineNum], 0, (int)words[lineNum].size()-1)), '(')[1]), ','), variableValues)); return nullType; } @@ -380,8 +403,10 @@ boost::any ProcessLine(const vector>& words, int lineNum, unorder // Check existing variables: To see if class sub component matches else if (count(words[lineNum][0], '.') > 0 && IsVar(split(words[lineNum][0], '.')[0], variableValues) || IsVar(split(words[lineNum][0], '.')[0], globalVariableValues)) { - // Evaluates what the operator (ex. '=', '+=') does to the value on the left by the value on the right - varOperation(vector(words[lineNum].begin(), words[lineNum].end()), variableValues); + if (IsVar(split(words[lineNum][0], '.')[0], variableValues)) + variableValues[split(words[lineNum][0], '.')[0]] = EditClassSubComponent(variableValues[split(words[lineNum][0], '.')[0]], words[lineNum][1], EvalExpression(unWrapVec(vector(words[lineNum].begin() + 2, words[lineNum].end())), variableValues), split(words[lineNum][0], '.')[1]); + else if (IsVar(split(words[lineNum][0], '.')[0], globalVariableValues)) + globalVariableValues[split(words[lineNum][0], '.')[0]] = EditClassSubComponent(globalVariableValues[split(words[lineNum][0], '.')[0]], words[lineNum][1], EvalExpression(unWrapVec(vector(words[lineNum].begin() + 2, words[lineNum].end())), variableValues), split(words[lineNum][0], '.')[1]); return nullType; } @@ -502,7 +527,7 @@ boost::any ExecuteFunction(const string& functionName, const vector& for (int i = 0; i < (int)inputVarVals.size(); i++) { variableValues[args[i]] = inputVarVals[i]; - //cout << "\x1B[33m" << args[i] << " == " << AnyAsString(inputVarVals[i]) << "\033[0m\t\t" << endl; + //cout << functionName + " \x1B[33m" << args[i] << " == " << AnyAsString(inputVarVals[i]) << "\033[0m\t\t" << endl; } //Iterate through all lines in function @@ -543,12 +568,13 @@ int parseSlang(string script) string functName = split(words[lineNum][1], '(')[0]; string args = ""; - for (int w = 1; w < (int)words[lineNum].size(); w++) // Get all words from the instantiation line: these are the args - { - args += replace(replace(words[lineNum][w], "(", " "), ")", ""); - } + if (indexInStr(unWrapVec(words[lineNum]), ')') - indexInStr(unWrapVec(words[lineNum]), '(') > 1) + for (int w = 1; w < (int)words[lineNum].size(); w++) // Get all words from the instantiation line: these are the args + { + args += replace(replace(words[lineNum][w], "(", " "), ")", ""); + } - args = replace(args, functName + " ", ""); + args = trim(replace(args, functName + " ", "")); //InterpreterLog(args); functionContents.push_back(split(args, ',')); diff --git a/Slang/anyops.h b/Slang/anyops.h index fb39ce5..c338e6b 100644 --- a/Slang/anyops.h +++ b/Slang/anyops.h @@ -9,6 +9,7 @@ using namespace boost; using namespace std; int LogWarning(const string& warningText); +int any_type(const boost::any& val); // Gets if any is NullType bool any_null(const boost::any& val) @@ -45,7 +46,7 @@ bool AnyAsBool(const boost::any& val) } catch (boost::bad_any_cast) // Does not convert, return { - LogWarning("invalid conversion to type \'bool\'"); + LogWarning("invalid conversion from " + to_string(any_type(val)) + " to type \'bool\'"); return false; } } @@ -84,7 +85,7 @@ string AnyAsString(const boost::any& val) } catch (boost::bad_any_cast) // Does not convert, return { - LogWarning("invalid conversion to type \'string\'"); + LogWarning("invalid conversion from " + to_string(any_type(val)) + " to type \'string\'"); return ""; } } @@ -123,7 +124,7 @@ float AnyAsFloat(const boost::any& val) } catch (boost::bad_any_cast e) // Does not convert, return { - LogWarning("invalid conversion to type \'float\'"); + LogWarning("invalid conversion from " + to_string(any_type(val)) + " to type \'float\'"); return 0; } } @@ -162,7 +163,7 @@ int AnyAsInt(const boost::any& val) } catch (boost::bad_any_cast) // Does not convert, return { - LogWarning("invalid conversion to type \'int\'"); + LogWarning("invalid conversion from " + to_string(any_type(val)) + " to type \'int\'"); return 0; } } @@ -170,8 +171,38 @@ int AnyAsInt(const boost::any& val) } } +// Will get type 'any' val to a Vec2 +Vec2 AnyAsVec2(const boost::any& val) +{ + if (any_null(val)) + return Vec2(0, 0); + try // Try converting to Vec2 + { + return any_cast(val); + } + catch (boost::bad_any_cast) + { + try // Try converting to float then Vec2 + { + return Vec2(any_cast(val), any_cast(val)); + } + catch (boost::bad_any_cast) + { + try // Try converting to int then Vec2 + { + return Vec2(any_cast(val), any_cast(val)); + } + catch (boost::bad_any_cast) // Does not convert, return + { + LogWarning("invalid conversion from " + to_string(any_type(val)) + " to type \'Vec2\'"); + return Vec2(0, 0); + } + } + } +} + // Gets type of 'any' val -// 0 -> int; 1 -> float; 2 -> bool; 3 -> string; 4 -> Sprite; 5 -> Vec2; +// 0 -> int; 1 -> float; 2 -> bool; 3 -> string; 4 -> Sprite; 5 -> Vec2; 6 -> Text; int any_type(const boost::any& val) { try // Try converting to int @@ -214,10 +245,18 @@ int any_type(const boost::any& val) Vec2 v = any_cast(val); return 5; } - catch (boost::bad_any_cast) // Does not convert, return + catch (boost::bad_any_cast) // Try converting to Text { - LogWarning("variable has no type"); - return -1; + try + { + Text t = any_cast(val); + return 6; + } + catch (boost::bad_any_cast) // Does not convert, return + { + LogWarning("variable has no type"); + return -1; + } } } } @@ -226,4 +265,27 @@ int any_type(const boost::any& val) } } +// Compares two 'any' values to see if they contain the same data +bool any_compare(const boost::any& a, const boost::any& b) +{ + int aType = any_type(a); + int bType = any_type(b); + + // If they are different types, then they can't possibly be equal + if ((aType > 3 && bType <= 3) || (aType <= 3 && bType > 3)) + return false; + + // If it is a float, int, bool, or string, then they can easily be compared in their string form + if (aType <= 3) + return AnyAsString(a) == AnyAsString(b); + + // If it is a Sprite, then compare separately after converted + else if (aType == 4) + return any_cast(a) == any_cast(b); + + // If it is a Vec2, then compare separately after converted + else if (aType == 5) + return any_cast(a) == any_cast(b); +} + #endif diff --git a/Slang/builtin.h b/Slang/builtin.h index e72c1ef..929f3eb 100644 --- a/Slang/builtin.h +++ b/Slang/builtin.h @@ -97,28 +97,26 @@ int LogCriticalError(const string& errorText) boost::any GetClassSubComponent(boost::any value, string subComponentName) { + // If a Sprite Class + if (any_type(value) == 4) + { + return any_cast(value).SubComponent(subComponentName); + } // If a Vec2 Class if (any_type(value) == 5) { return any_cast(value).SubComponent(subComponentName); } - // If a Sprite Class - if (any_type(value) == 4) + // If a Text Class + if (any_type(value) == 6) { - return any_cast(value).SubComponent(subComponentName); + return any_cast(value).SubComponent(subComponentName); } return nullType; } boost::any EditClassSubComponent(boost::any value, string oper, boost::any otherVal, string subComponentName) { - // If a Vec2 Class - if (any_type(value) == 5) - { - Vec2 v = any_cast(value); - v.EditSubComponent(subComponentName, oper, otherVal); - return v; - } // If a Sprite Class if (any_type(value) == 4) { @@ -126,20 +124,42 @@ boost::any EditClassSubComponent(boost::any value, string oper, boost::any other v.EditSubComponent(subComponentName, oper, otherVal); return v; } + // If a Vec2 Class + if (any_type(value) == 5) + { + Vec2 v = any_cast(value); + v.EditSubComponent(subComponentName, oper, otherVal); + return v; + } + // If a Text Class + if (any_type(value) == 6) + { + Text t = any_cast(value); + t.EditSubComponent(subComponentName, oper, otherVal); + return t; + } return nullType; } bool AxisAlignedCollision(const Sprite& a, const Sprite& b) // AABB - AABB collision { - // collision x-axis? - bool collisionX = a.position.x + a.scale.x >= b.position.x && - b.position.x + b.scale.x >= a.position.x; - // collision y-axis? - bool collisionY = a.position.y + a.scale.y >= b.position.y && - b.position.y + b.scale.y >= b.position.y; - // collision only if on both axes - return collisionX && collisionY; -} + // collision x-axis? + bool collisionX = a.position.x + a.scale.x >= b.position.x && + b.position.x + b.scale.x >= a.position.x; + // collision y-axis? + bool collisionY = a.position.y + a.scale.y >= b.position.y && + b.position.y + b.scale.y >= a.position.y; + + //// collision x-axis? + //bool collisionX = a.position.x - a.scale.x / 2 >= b.position.x + b.scale.x / 2 || + // a.position.x + a.scale.x / 2 <= b.position.x - b.scale.x / 2; + //// collision y-axis? + //bool collisionY = a.position.y - a.scale.y / 2 >= b.position.y + b.scale.y / 2 || + // a.position.y + a.scale.y / 2 <= b.position.y - b.scale.y / 2; + + // collision only if on both axes + return collisionX && collisionY; +} // Initial script processing, which loads variables and functions from builtin int GetBuiltins(const string& s) @@ -217,56 +237,60 @@ int GetBuiltins(const string& s) } // Executes -boost::any CPPFunction(const string& name, const vector& args) +boost::any SLBFunction(const string& name, const vector& args) { - if (name == "CPP.Math.Sin") + if (name == "SLB.Math.Sin") return sin(AnyAsFloat(args[0])); - else if (name == "CPP.Math.Cos") + else if (name == "SLB.Math.Cos") return cos(AnyAsFloat(args[0])); - else if (name == "CPP.Math.Tan") + else if (name == "SLB.Math.Tan") return tan(AnyAsFloat(args[0])); - else if (name == "CPP.Math.Round") + else if (name == "SLB.Math.Round") return AnyAsInt(args[0]); - else if (name == "CPP.Math.Lerp") + else if (name == "SLB.Math.Lerp") return lerp(AnyAsFloat(args[0]), AnyAsFloat(args[1]), AnyAsFloat(args[2])); - else if (name == "CPP.Math.Abs") + else if (name == "SLB.Math.Abs") return abs(AnyAsFloat(args[0])); - else if (name == "CPP.Graphics.Init") + else if (name == "SLB.Graphics.Init") { InterpreterLog("Init graphics"); initGraphics(StringRaw(AnyAsString(args[0])), AnyAsInt(args[1]), AnyAsInt(args[2])); } - else if (name == "CPP.Graphics.Sprite") + else if (name == "SLB.Graphics.Sprite") { Sprite s(StringRaw(AnyAsString(args[0])), any_cast(args[1]), any_cast(args[2]), AnyAsFloat(args[3])); return s; } - else if (name == "CPP.Graphics.Draw") + else if (name == "SLB.Graphics.Draw") any_cast(args[0]).Draw(); - else if (name == "CPP.Graphics.Text") + else if (name == "SLB.Graphics.Load") + any_cast(args[0]).Load(); + else if (name == "SLB.Graphics.Text") { - Text t(StringRaw(AnyAsString(args[0])), any_cast(args[1]), any_cast(args[2]), AnyAsFloat(args[3]), AnyAsFloat(args[4]), AnyAsFloat(args[5]), AnyAsFloat(args[6]), AnyAsFloat(args[7])); + Text t(StringRaw(AnyAsString(args[0])), StringRaw(AnyAsString(args[1])), any_cast(args[2]), AnyAsFloat(args[3]), AnyAsFloat(args[4]), AnyAsFloat(args[5]), AnyAsFloat(args[6]), AnyAsFloat(args[7])); return t; } - else if (name == "CPP.Graphics.DrawText") + else if (name == "SLB.Graphics.DrawText") any_cast(args[0]).Draw(); - else if (name == "CPP.Physics.AxisAlignedCollision") + else if (name == "SLB.Graphics.LoadText") + any_cast(args[0]).Load(); + else if (name == "SLB.Physics.AxisAlignedCollision") { return AxisAlignedCollision(any_cast(args[0]), any_cast(args[1])); } - else if (name == "CPP.Input.GetKey") + else if (name == "SLB.Input.GetKey") return KEYS[StringRaw(any_cast(args[0]))] == 1; - else if (name == "CPP.System.Print") + else if (name == "SLB.System.Print") cout << StringRaw(AnyAsString(args[0])); - else if (name == "CPP.System.PrintLine") + else if (name == "SLB.System.PrintLine") cout << StringRaw(AnyAsString(args[0])) << endl; - else if (name == "CPP.System.Vec2") + else if (name == "SLB.System.Vec2") { Vec2 v(AnyAsFloat(args[0]), AnyAsFloat(args[1])); return v; } else - LogWarning("CPP function \'" + name + "\' does not exist."); + LogWarning("SLB function \'" + name + "\' does not exist."); return nullType; } diff --git a/Slang/builtin.slg b/Slang/builtin.slg index 8e3baac..369fbb9 100644 --- a/Slang/builtin.slg +++ b/Slang/builtin.slg @@ -6,21 +6,21 @@ float EulersNumber = 2.71828183 // Trigonometric function Sin func Sin(input) { - float out = CPP.Math.Sin(input) + float out = SLB.Math.Sin(input) return out } // Trigonometric function Cos func Cos(input) { - float out = CPP.Math.Cos(input) + float out = SLB.Math.Cos(input) return out } // Trigonometric function Tan func Tan(input) { - float out = CPP.Math.Tan(input) + float out = SLB.Math.Tan(input) return out } @@ -41,21 +41,21 @@ func Tanh(input) // Rounds input to nearest integer value func Round(input) { - float out = CPP.Math.Round(input) + float out = SLB.Math.Round(input) return out } // Linearly interpolates between a and b by t func Lerp(a, b, t) { - float out = CPP.Math.Lerp(a, b, t) + float out = SLB.Math.Lerp(a, b, t) return out } // Get absolute value of x func Abs(x) { - float out = CPP.Math.Abs(x) + float out = SLB.Math.Abs(x) return out } @@ -90,45 +90,45 @@ func Clamp(input, min, max) // Sets color of pixel to RGB value func SetPixel(x, y, r, g, b) { - string out = CPP.Graphics.SetPixel(x, y, r, g, b) + string out = SLB.Graphics.SetPixel(x, y, r, g, b) return out } // Prints input value to console func Print(in) { - CPP.System.Print(in) + SLB.System.Print(in) } // Prints input value to console with appended newline '\n' func Printl(in) { - CPP.System.PrintLine(in) + SLB.System.PrintLine(in) } // Creates new sprite class func NSprite(path, x, y, r) { - Sprite s = CPP.Graphics.Sprite(path, x, y, r) + Sprite s = SLB.Graphics.Sprite(path, x, y, r) return s } // Draws sprite to window func Draw(spr) { - CPP.Graphics.Draw(spr) + SLB.Graphics.Draw(spr) } // Creates new Vector2 class func NVec2(x, y) { - Vec2 v = CPP.System.Vec2(x, y) + Vec2 v = SLB.System.Vec2(x, y) return v } // Gets if key is down func GetKey(keyName) { - bool b = CPP.Input.GetKey(keyName) + bool b = SLB.Input.GetKey(keyName) return b } diff --git a/Slang/eval.cpp b/Slang/eval.cpp index 1d2d422..d40e071 100644 --- a/Slang/eval.cpp +++ b/Slang/eval.cpp @@ -1,4 +1,4 @@ -// CPP program to evaluate a given expression +// SLB program to evaluate a given expression #include #include #include @@ -35,7 +35,8 @@ float applyOp(const float& a, const float& b, const char& op) { // Function that returns value of // expression after evaluation. -float evaluate(const string& t) { +float evaluate(const string& t) +{ string tokens = replace(t, " ", ""); float i; @@ -44,16 +45,11 @@ float evaluate(const string& t) { stack ops; bool negative = false; - for (i = 0; i < tokens.length(); i++) { - - // Current token is a whitespace, - // skip it. - if (tokens[i] == ' ') - continue; - + for (i = 0; i < tokens.length(); i++) + { // Current token is an opening // brace, push it to 'ops' - else if (tokens[i] == '(') + if (tokens[i] == '(') { ops.push(tokens[i]); } @@ -116,7 +112,7 @@ float evaluate(const string& t) { // Current token is an operator. else { - if (tokens[i] == '-' && (i == 0 || tokens[i-1] == '*' || tokens[i-1] == '/' || tokens[i-1] == '+' || tokens[i-1] == '-' || tokens[i-1] == '^')) + if (tokens[i] == '-' && (i == 0 || tokens[i-1] == '*' || tokens[i-1] == '/' || tokens[i-1] == '+' || tokens[i-1] == '-' || tokens[i-1] == '^' || tokens[i-1] == '(' || tokens[i-1] == ')')) { negative = true; continue; diff --git a/Slang/graphics.h b/Slang/graphics.h index 70eb436..df95bf4 100644 --- a/Slang/graphics.h +++ b/Slang/graphics.h @@ -206,6 +206,11 @@ public: return *this; } + bool operator==(Vec2 other) + { + return x == other.x && y == other.y; + } + boost::any SubComponent(std::string componentName) { if (componentName == "x") @@ -376,6 +381,11 @@ public: return 0; } + bool operator==(Sprite other) + { + return position == other.position && angle == other.angle && scale == other.scale && texture == other.texture; + } + boost::any SubComponent(std::string componentName) { if (componentName == "position") @@ -394,6 +404,7 @@ public: Sprite EditSubComponent(std::string componentName, std::string oper, boost::any otherVal) { + //cout << ("ComponentName = " + componentName + " Op = " + oper + " OtherVal = " + AnyAsString(otherVal)) << endl; if (componentName == "position") { if (oper == "=") @@ -500,15 +511,17 @@ public: int Load() { - TTF_Font* font = TTF_OpenFont(pathToFont, fontSize); + TTF_Font* font = TTF_OpenFont(pathToFont.c_str(), fontSize); SDL_Color color = {r, g, b}; - SDL_Surface* surface = TTF_RenderText_Solid(font, content, color); + SDL_Surface* surface = TTF_RenderText_Solid(font, content.c_str(), color); texture = SDL_CreateTextureFromSurface(gRenderer, surface); - TTF_SizeText(font, Message, &rect.w, &rect.h); + TTF_SizeText(font, content.c_str(), &rect.w, &rect.h); + scale.x = rect.w; + scale.y = rect.h; SDL_FreeSurface(surface); return 0; @@ -516,20 +529,25 @@ public: int Draw() { - rect.x = position.x; - rect.y = position.y; SDL_RenderCopy(gRenderer, texture, NULL, &rect); return 0; } boost::any SubComponent(std::string componentName) { + //cerr << componentName << endl; if (componentName == "position") return position; if (componentName == "position.x") return position.x; if (componentName == "position.y") return position.y; + if (componentName == "scale") + return scale; + if (componentName == "scale.x") + return scale.x; + if (componentName == "scale.y") + return scale.y; if (componentName == "fontSize") return fontSize; if (componentName == "content") @@ -538,8 +556,9 @@ public: return pathToFont; } - Sprite EditSubComponent(std::string componentName, std::string oper, boost::any otherVal) + Text EditSubComponent(const std::string componentName, const std::string oper, const boost::any otherVal) { + //cerr << componentName << " " << AnyAsString(otherVal) << endl; if (componentName == "position") { if (oper == "=") @@ -645,6 +664,7 @@ public: } Vec2 position; + Vec2 scale; float fontSize; double angle; int r; diff --git a/Slang/script.slg b/Slang/script.slg index 308875f..e77f8d2 100644 --- a/Slang/script.slg +++ b/Slang/script.slg @@ -4,16 +4,16 @@ int SCREENH = 600 int scoreOne = 0 int scoreTwo = 0 -float ballSpeed = 3 +float ballSpeed = 8 -float paddleMoveSpeed = 7 +float paddleMoveSpeed = 16 // Main is always run at the VERY BEGINNING. Start() is the start of GRAPHICS -// so if you never call CPP.Grapgics.Init, then Start won't run +// so if you never call SLB.Grapgics.Init, then Start won't run func Main(input, in) { // Immediately creates the window, then Start(), then the game loop. The game loop calls Update() every frame - CPP.Graphics.Init("This is a pong game", SCREENW, SCREENH) + SLB.Graphics.Init("This is a pong game", SCREENW, SCREENH) } func Start() @@ -22,11 +22,12 @@ func Start() float centerY = SCREENH / 2 global Vec2 centerOfScreen = NVec2(centerX, centerY) - Vec2 ballScale = NVec2(16, 16) - Vec2 ballPos = centerOfScreen - ballScale + Vec2 ballScale = NVec2(10, 10) + Vec2 ballPos = centerOfScreen + ballPos -= ballScale - Vec2 paddleScale = NVec2(16, 70) - float yPosPaddle = yPosBall - paddleScale.y / 2 + Vec2 paddleScale = NVec2(4, 70) + float yPosPaddle = ballPos.y - (paddleScale.y / 2) Vec2 lPaddlePosition = NVec2(15, yPosPaddle) global Vec2 lPaddleTargetPosition = NVec2(15, yPosPaddle) @@ -35,13 +36,18 @@ func Start() Vec2 rPaddlePosition = NVec2(rOffset, yPosPaddle) global Vec2 rPaddleTargetPosition = NVec2(rOffset, yPosPaddle) - global Sprite ballSpr = CPP.Graphics.Sprite("./square.png", ballPos, ballScale, 0) - global Sprite lPaddle = CPP.Graphics.Sprite("./square.png", lPaddlePosition, paddleScale, 0) - global Sprite rPaddle = CPP.Graphics.Sprite("./square.png", rPaddlePosition, paddleScale, 0) + global Sprite ballSpr = SLB.Graphics.Sprite("./square.png", ballPos, ballScale, 0) + global Sprite lPaddle = SLB.Graphics.Sprite("./square.png", lPaddlePosition, paddleScale, 0) + global Sprite rPaddle = SLB.Graphics.Sprite("./square.png", rPaddlePosition, paddleScale, 0) - // global Text scoreTextOne = CPP.Graphics.Text("score", "./Arial.ttf", centerOfScreen, 20, 0, 255, 255, 255) + float leftOffset = SCREENW / 4 + Vec2 scoreOnePos = NVec2(leftOffset - 40, 30) + global Text scoreTextOne = SLB.Graphics.Text("score", "./arial.ttf", scoreOnePos, 40, 0, 255, 255, 255) + float rightOffset = SCREENW - (SCREENW / 4) + Vec2 scoreTwoPos = NVec2(rightOffset - 40, 30) + global Text scoreTextTwo = SLB.Graphics.Text("score", "./arial.ttf", scoreTwoPos, 40, 0, 255, 255, 255) - global Vec2 ballVelocity = NVec2(ballSpeed, 0) + global Vec2 ballVelocity = NVec2(ballSpeed, ballSpeed) } func Update(deltaTime) @@ -58,6 +64,7 @@ func Update(deltaTime) float newY = lPaddleTargetPosition.y - paddleMoveSpeed newY = Clamp(newY, 0, SCREENH - 70) lPaddleTargetPosition = NVec2(newX, newY) + print "MOVE UP" } if GetKey("S") == true { @@ -66,6 +73,7 @@ func Update(deltaTime) float newY = lPaddleTargetPosition.y + paddleMoveSpeed newY = Clamp(newY, 0, SCREENH - 70) lPaddleTargetPosition = NVec2(newX, newY) + print "MOVE DOWN" } // Lerps from old position to destination smoothly float oldY = lPaddle.position.y @@ -102,11 +110,12 @@ func Update(deltaTime) ballSpr.position += ballVelocity // Finally draws all of the sprites - CPP.Graphics.Draw(ballSpr) - CPP.Graphics.Draw(lPaddle) - CPP.Graphics.Draw(rPaddle) + SLB.Graphics.Draw(ballSpr) + SLB.Graphics.Draw(lPaddle) + SLB.Graphics.Draw(rPaddle) - // scoreTextOne.DrawText() + SLB.Graphics.DrawText(scoreTextOne) + SLB.Graphics.DrawText(scoreTextTwo) HandleBallBounce() } @@ -117,39 +126,52 @@ func HandleBallBounce() float ballY = ballSpr.position.y float scaleY = ballSpr.scale.y + float topEdge = ballY - scaleY // Checks if the ball is touching the ceiling - if ballY - scaleY <= 0 + if topEdge <= 0 { - ballVelocity = NVec2(ballVelocity.x, -ballVelocity.y) + float vX = ballVelocity.x + float vY = ballVelocity.y + vY *= -1 + ballVelocity = NVec2(vX, vY) return 0 } + float bottomEdge = ballY + scaleY // Checks if the ball is touching the floor - if ballY + scaleY >= SCREENH + if bottomEdge >= SCREENH { - ballVelocity = NVec2(ballVelocity.x, -ballVelocity.y) + float vX = ballVelocity.x + float vY = ballVelocity.y + vY *= -1 + ballVelocity = NVec2(vX, vY) return 0 } // Checks if ball is in player 1 goal if ballX < 0 { - Vec2 ballScale = NVec2(16, 16) - Vec2 ballPos = centerOfScreen - ballScale + Vec2 ballPos = centerOfScreen + ballPos -= ballSpr.scale + ballPos.x -= SCREENW / 3 scoreTwo += 1 ballSpr.position = ballPos ballVelocity = NVec2(ballSpeed, 0) - return 0 + scoreTextTwo.content = Round(scoreTwo) + print scoreTextTwo.content + SLB.Graphics.LoadText(scoreTextTwo) } // Checks if ball is in player 2 goal if ballX > SCREENW { - Vec2 ballScale = NVec2(16, 16) - Vec2 ballPos = centerOfScreen - ballScale + Vec2 ballPos = centerOfScreen + ballPos -= ballSpr.scale + ballPos.x += SCREENW / 3 scoreOne += 1 ballSpr.position = ballPos ballVelocity = NVec2(-ballSpeed, 0) - // scoreTextOne.content = scoreOne - return 0 + scoreTextOne.content = Round(scoreOne) + print scoreTextOne.content + SLB.Graphics.LoadText(scoreTextOne) } // Checks if colliding with left paddle @@ -158,12 +180,15 @@ func HandleBallBounce() { float difference = lPaddle.position.y difference -= ballY - float normalizedRelativeIntersectionY = (difference/(lPaddle.scale.y/2)) - float bounceAngle = normalizedRelativeIntersectionY * 1.30899694 - float ballVx = ballSpeed*Cos(bounceAngle) - float ballVy = ballSpeed*-Sin(bounceAngle) + float paddleHeight = lPaddle.scale.y + float normalizedRelativeIntersectionY = difference / (paddleHeight / 2) + float bounceAngle = normalizedRelativeIntersectionY * 0.523599 + float ballVx = ballSpeed + ballVx *= Cos(bounceAngle) + float ballVy = ballSpeed + ballVy *= Sin(bounceAngle) + ballVy *= -1 ballVelocity = NVec2(ballVx, ballVy) - return 0 } // Checks if colliding with right paddle bool coll = Colliding(ballSpr, rPaddle) @@ -171,17 +196,20 @@ func HandleBallBounce() { float difference = rPaddle.position.y difference -= ballY - float normalizedRelativeIntersectionY = (difference/(rPaddle.scale.y/2)) - float bounceAngle = normalizedRelativeIntersectionY * 1.30899694 - float ballVx = ballSpeed*Cos(bounceAngle) - float ballVy = ballSpeed*-Sin(bounceAngle) + float paddleHeight = rPaddle.scale.y + float normalizedRelativeIntersectionY = difference / (paddleHeight / 2) + float bounceAngle = normalizedRelativeIntersectionY * 0.523599 + float ballVx = ballSpeed + ballVx *= Cos(bounceAngle) + ballVx *= -1 + float ballVy = ballSpeed + ballVy *= Sin(bounceAngle) ballVelocity = NVec2(ballVx, ballVy) - return 0 } } func Colliding(a, b) { - bool b = CPP.Physics.AxisAlignedCollision(a, b) + bool b = SLB.Physics.AxisAlignedCollision(a, b) return b } diff --git a/Slang/strops.cpp b/Slang/strops.cpp index 5735166..0c4b2d4 100644 --- a/Slang/strops.cpp +++ b/Slang/strops.cpp @@ -131,7 +131,8 @@ int count(const string& str, const char& ch) { return cnt; } -int countNoOverlap(const string& str, const char& ch1, const char& ch2) { +int countNoOverlap(const string& str, const char& searchFor, const char& ch1, const char& ch2) +{ int cnt = 0; bool waitingForClose = false; @@ -141,10 +142,28 @@ int countNoOverlap(const string& str, const char& ch1, const char& ch2) { if (str[i] == ch1) waitingForClose = true; else if (str[i] == ch2 && waitingForClose == true) - { - cnt++; waitingForClose = false; - } + else if (str[i] == searchFor && waitingForClose == true) + cnt++; + } + + return cnt; +} + +int countOutsideParenthesis(const string& str, const char& searchFor) +{ + int cnt = 0; + + bool waitingForClose = false; + + for (int i = 0; i < (int)str.size(); i++) + { + if (str[i] == '(') + waitingForClose = true; + else if (str[i] == ')' && waitingForClose == true) + waitingForClose = false; + else if (str[i] == searchFor && waitingForClose == false) + cnt++; } return cnt; diff --git a/Slang/strops.h b/Slang/strops.h index abf0353..215f29f 100644 --- a/Slang/strops.h +++ b/Slang/strops.h @@ -7,6 +7,9 @@ using namespace std; float AnyAsFloat(const boost::any& val); +string AnyAsString(const boost::any& val); +int AnyAsInt(const boost::any& val); +bool AnyAsBool(const boost::any& val); bool isNumber(const string& str); @@ -29,7 +32,9 @@ vector split(const string& str, const char& del); int count(const string& str, const char& ch); -int countNoOverlap(const string& str, const char& ch1, const char& ch2); +int countNoOverlap(const string& str, const char& searchFor, const char& ch1, const char& ch2); + +int countOutsideParenthesis(const string& str, const char& searchFor); int indexInStr(const string& str, const char& ch);